Skip to content

Commit

Permalink
Create healthcheck command (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
jazzman committed Apr 16, 2023
2 parents 8a56179 + 4e9e42b commit e24788e
Show file tree
Hide file tree
Showing 17 changed files with 459 additions and 14 deletions.
22 changes: 16 additions & 6 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,19 @@ jobs:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker login
docker pull ${{ secrets.DOCKER_USERNAME }}/odmiana:${{ needs.version.outputs.new_tag }}
docker stop odmiana
docker rm odmiana
docker run --detach --name odmiana --network ec2-user_odmiana_network -e MONGO_HOST -e MONGO_USERNAME -e MONGO_PASSWORD -e TELEGRAM_USERNAME -e TELEGRAM_TOKEN -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/odmiana:${{ needs.version.outputs.new_tag }}
script:
- docker login
- docker pull ${{ secrets.DOCKER_USERNAME }}/odmiana:${{ needs.version.outputs.new_tag }}
- docker stop odmiana
- docker rm odmiana
- |
docker run --detach --name odmiana --network ec2-user_odmiana_network
-e MONGO_HOST
-e MONGO_USERNAME
-e MONGO_PASSWORD
-e TELEGRAM_USERNAME
-e TELEGRAM_TOKEN
-e OWNER_ID
-e VERSION=${{ needs.version.outputs.new_tag }}
-p 8080:8080
${{ secrets.DOCKER_USERNAME }}/odmiana:${{ needs.version.outputs.new_tag }}
8 changes: 6 additions & 2 deletions src/main/java/pro/jazzman/odmiana/bot/OdmianaBot.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import org.telegram.telegrambots.meta.generics.BotOptions;
import org.telegram.telegrambots.meta.generics.LongPollingBot;
import pro.jazzman.odmiana.bot.interfaces.Privacy;
import pro.jazzman.odmiana.configurations.Config;
import pro.jazzman.odmiana.exceptions.ApplicationRuntimeException;
import pro.jazzman.odmiana.bot.services.Commands;

Expand All @@ -21,17 +23,19 @@
@Slf4j
public class OdmianaBot implements LongPollingBot {
private final TelegramLongPollingBot bot;
private final Config config;
private final Commands commands;

@Autowired
public OdmianaBot(TelegramLongPollingBot bot, Commands commands) {
public OdmianaBot(TelegramLongPollingBot bot, Config config, Commands commands) {
this.bot = bot;
this.config = config;
this.commands = commands;
}

public void setMyCommands() throws TelegramApiException {
bot.execute(
new SetMyCommands(commands.asBotCommands(), new BotCommandScopeDefault(), "en")
new SetMyCommands(commands.asBotCommands(Privacy.PUBLIC), new BotCommandScopeDefault(), "en")
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package pro.jazzman.odmiana.bot.commands;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import pro.jazzman.odmiana.bot.OdmianaBot;
import pro.jazzman.odmiana.bot.interfaces.Command;
import pro.jazzman.odmiana.bot.interfaces.Privacy;
import pro.jazzman.odmiana.bot.messages.HealthcheckView;
import pro.jazzman.odmiana.configurations.Config;

import java.util.Objects;

@Service
public class HealthcheckCommand implements Command {
@Autowired
private Config config;

@Autowired
private HealthcheckView view;

@Override
public String getCommand() {
return "/healthcheck";
}

@Override
public String getUsage() {
return "/healthcheck";
}

@Override
public String getDescription() {
return "Application Healthcheck";
}

public Privacy privacy() {
return Privacy.OWNER;
}

@Override
public void handle(OdmianaBot bot, Update update) throws TelegramApiException {
if (Objects.equals(config.getOwnerId(), update.getMessage().getChatId())) {
bot.send(
view.render(),
update
);
}
}
}
4 changes: 4 additions & 0 deletions src/main/java/pro/jazzman/odmiana/bot/interfaces/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public interface Command {
*/
String getDescription();

default Privacy privacy() {
return Privacy.PUBLIC;
}

/**
* Fired when user types in /command arg0 arg1 arg2..
*
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/pro/jazzman/odmiana/bot/interfaces/Privacy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package pro.jazzman.odmiana.bot.interfaces;

public enum Privacy {
PUBLIC,
OWNER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package pro.jazzman.odmiana.bot.messages;

import org.apache.commons.text.StringSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pro.jazzman.odmiana.entities.Healthcheck;
import pro.jazzman.odmiana.services.HealthcheckService;

import java.util.HashMap;
import java.util.Map;

@Service
public class HealthcheckView {
private final HealthcheckService service;

@Autowired
public HealthcheckView(HealthcheckService service) {
this.service = service;
}

private static final String TEMPLATE = """
Version: *${version}*
Status: *${application.status}*
Database: *${database.status}*
""";

public String render() {
Healthcheck healthcheck = service.get();

Map<String, String> placeholders = new HashMap<>();
placeholders.put("version", healthcheck.getVersion());
placeholders.put("application.status", healthcheck.getStatus());
placeholders.put("database.status", healthcheck.getDatabase());

return StringSubstitutor.replace(TEMPLATE, placeholders);
}
}
5 changes: 5 additions & 0 deletions src/main/java/pro/jazzman/odmiana/bot/services/Commands.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.telegram.telegrambots.meta.api.objects.commands.BotCommand;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import pro.jazzman.odmiana.bot.OdmianaBot;
import pro.jazzman.odmiana.bot.interfaces.Privacy;
import pro.jazzman.odmiana.bot.replies.DefaultReply;
import pro.jazzman.odmiana.bot.interfaces.Command;

Expand Down Expand Up @@ -40,6 +41,10 @@ public List<BotCommand> asBotCommands() {
return items.stream().map(c -> new BotCommand(c.getCommand(), c.getDescription())).toList();
}

public List<BotCommand> asBotCommands(Privacy privacy) {
return items.stream().filter(c -> c.privacy() == privacy).map(c -> new BotCommand(c.getCommand(), c.getDescription())).toList();
}

public boolean isCommand(String command) {
return items.stream().anyMatch(c -> command.equals(c.getCommand()));
}
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/pro/jazzman/odmiana/configurations/Config.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package pro.jazzman.odmiana.configurations;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import pro.jazzman.odmiana.bot.LongPollingBot;

@Configuration
@Getter
@Setter
public class Config {
@Value("${bot.owner_id}")
private Long ownerId;

@Value("${bot.version}")
private String version;

@Bean
public LongPollingBot bot(@Value("${TELEGRAM_USERNAME}") String username, @Value("${TELEGRAM_TOKEN}") String token) {
return new LongPollingBot(username, token);
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/pro/jazzman/odmiana/entities/Healthcheck.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package pro.jazzman.odmiana.entities;

import lombok.Data;

@Data
public class Healthcheck {
private final String version;
private final String status;
private final String database;
}
42 changes: 42 additions & 0 deletions src/main/java/pro/jazzman/odmiana/services/HealthcheckService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package pro.jazzman.odmiana.services;

import com.mongodb.client.MongoClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pro.jazzman.odmiana.configurations.Config;
import pro.jazzman.odmiana.configurations.SimpleMongoConfig;
import pro.jazzman.odmiana.entities.Healthcheck;

@Service
public class HealthcheckService {
private static final String STATUS_FAILED = "FAILED";
private static final String STATUS_OK = "OK";

private final Config config;
private final SimpleMongoConfig mongoConfig;
@Autowired
public HealthcheckService(Config config, SimpleMongoConfig mongoConfig) {
this.config = config;
this.mongoConfig = mongoConfig;
}

public Healthcheck get() {
return new Healthcheck(config.getVersion(), status(), databaseStatus());
}

private String databaseStatus() {
try (MongoClient client = mongoConfig.mongo()) {
return STATUS_OK;
} catch (Exception e) {
return STATUS_FAILED;
}
}

/**
* Summary status of the application. Only checking database connection for now.
* @return OK if application is alive, FAILED - otherwise
*/
private String status() {
return STATUS_OK.equals(databaseStatus()) ? STATUS_OK : STATUS_FAILED;
}
}
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ sjp:
url: https://sjp.pl
wikislownik:
url: https://pl.wiktionary.org/w/api.php?action=parse&format=json&prop=text|categories&page=
bot:
owner_id: ${OWNER_ID}
version: ${VERSION:unknown}
5 changes: 4 additions & 1 deletion src/test/java/pro/jazzman/odmiana/bot/OdmianaBotTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
import pro.jazzman.odmiana.bot.interfaces.Command;
import pro.jazzman.odmiana.bot.services.Commands;
import pro.jazzman.odmiana.configurations.Config;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

Expand All @@ -32,12 +34,13 @@ class OdmianaBotTest {
private final Message message = new Message();

@Mock private AbstractTelegramBot bot;
@Mock private Config config;
@Mock private Commands commands;
@Mock private DefaultBotOptions botOptions;

@BeforeEach
void setUp() throws TelegramApiException {
odmianaBot = new OdmianaBot(bot, commands);
odmianaBot = new OdmianaBot(bot, config, commands);

var user = new User();
var chat = new Chat();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package pro.jazzman.odmiana.bot.commands;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.telegram.telegrambots.meta.api.objects.Chat;
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import pro.jazzman.odmiana.bot.OdmianaBot;
import pro.jazzman.odmiana.bot.interfaces.Privacy;
import pro.jazzman.odmiana.bot.messages.HealthcheckView;
import pro.jazzman.odmiana.configurations.Config;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
@DisplayName("Healthcheck command")
class HealthcheckCommandTest {
private static final Long OWNER_ID = 1L;
private static final String MESSAGE_TEXT = """
Version: *1.2.3*
Status: *OK*
Database: *OK*
""";

@Mock private OdmianaBot bot;
@Mock private Config config;
@Mock private HealthcheckView view;
private HealthcheckCommand command;

@BeforeEach
void init() {
command = new HealthcheckCommand();

ReflectionTestUtils.setField(command, "config", config);
ReflectionTestUtils.setField(command, "view", view);
}

@Test
@DisplayName("Has a correct command")
void getCommand() {
assertThat(command.getCommand()).isEqualTo("/healthcheck");
}

@Test
@DisplayName("Has a usage example")
void getUsage() {
assertThat(command.getUsage()).isEqualTo("/healthcheck");
}

@Test
@DisplayName("Has a description")
void getDescription() {
assertThat(command.getDescription()).isEqualTo("Application Healthcheck");
}

@Test
@DisplayName("Has OWNER privacy level")
void privacy() {
assertThat(command.privacy()).isEqualTo(Privacy.OWNER);
}

@Test
@DisplayName("Send message on the compatible privacy level")
void handle() throws TelegramApiException {
Chat chat = new Chat();
chat.setId(OWNER_ID);
Message message = new Message();
message.setChat(chat);
Update update = new Update();
update.setMessage(message);

when(config.getOwnerId()).thenReturn(OWNER_ID);
when(view.render()).thenReturn(MESSAGE_TEXT);

command.handle(bot, update);

verify(bot).send(MESSAGE_TEXT, update);
}

@Test
@DisplayName("Does nothing on incompatible privacy level")
void handleNotAllowedDoNothing() throws TelegramApiException {
Chat chat = new Chat();
chat.setId(100500L);
Message message = new Message();
message.setChat(chat);
Update update = new Update();
update.setMessage(message);

when(config.getOwnerId()).thenReturn(OWNER_ID);

command.handle(bot, update);

verify(bot, never()).send(any(), any());
}
}
Loading

0 comments on commit e24788e

Please sign in to comment.