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

[#87] Configuration of a Mongodb cluster instead of maintaining only a standalone instance #96

Merged
merged 53 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
834c4fb
feat: config mongodb cluster
levisingularity Jul 10, 2024
3fc50ce
docs: Update mongdb config
levisingularity Jul 10, 2024
2539add
feat: start mongodb cluster
levisingularity Jul 10, 2024
903d2cb
fix: recheable ssh connection
levisingularity Jul 10, 2024
186f5a0
fix: build cluster
levisingularity Jul 10, 2024
25530d8
fix: unset context
levisingularity Jul 11, 2024
1a12de5
fix: mongodb keyfile path
levisingularity Jul 11, 2024
59773c5
fix: generate keyfile
levisingularity Jul 11, 2024
bb07e81
feat: cluster node keyfile
levisingularity Jul 11, 2024
e61cbee
fix: generate cluster node keyfile
levisingularity Jul 11, 2024
6147b2d
fix: set keyfile
levisingularity Jul 11, 2024
dceff26
fix: keyfile path
levisingularity Jul 11, 2024
9903e73
fix: set keyfile text
levisingularity Jul 11, 2024
cc8d7cb
fix: keyfile server path
levisingularity Jul 11, 2024
3fe1696
fix: entrypoint
levisingularity Jul 11, 2024
d0fd3ec
feat: exec command
levisingularity Jul 12, 2024
f694eca
fix: get container status
levisingularity Jul 12, 2024
f1ad7ac
fix: replica setup
levisingularity Jul 12, 2024
58cd2da
fix: random keyfile name
levisingularity Jul 12, 2024
78311b1
fix: change keyfile gid and uid
levisingularity Jul 12, 2024
15a1160
fix: replica set config
levisingularity Jul 12, 2024
8760183
fix: syntax error
levisingularity Jul 12, 2024
fe81ed1
fix: replica set name
levisingularity Jul 12, 2024
4821d56
feat: raise exception when exec command code is not 0
levisingularity Jul 12, 2024
b6fd1e8
fix: use bash start cluster
levisingularity Jul 12, 2024
31ba4f5
fix: start cluster pass and username
levisingularity Jul 12, 2024
e15f5df
fix: wait mongodb container to be up
levisingularity Jul 12, 2024
0949e13
fix: wait for container to be healthy
levisingularity Jul 12, 2024
a4f7a5e
fix: container healthy
levisingularity Jul 12, 2024
d7ff279
fix: get client with context
levisingularity Jul 12, 2024
b3e7a50
fix: path
levisingularity Jul 12, 2024
568010e
feat: stop mongodb nodes
levisingularity Jul 12, 2024
246561d
feat: get mongodb cluster secret from settings
levisingularity Jul 12, 2024
fdddb0a
docs: add attr mongodb.cluster_secret_key
levisingularity Jul 12, 2024
d0d53ae
fix: redis_node
levisingularity Jul 12, 2024
84fb293
fix: typo
levisingularity Jul 12, 2024
62414e8
Remove repeated integration tests
levisingularity Jul 15, 2024
7713391
Fix config tests
levisingularity Jul 15, 2024
b66c57f
Check cluster_node first before try to upload mongodb keyfile
levisingularity Jul 15, 2024
9248925
Fix mongodb message
levisingularity Jul 15, 2024
c4bab98
Update db messages
levisingularity Jul 15, 2024
6075bf3
Fix db tests
levisingularity Jul 15, 2024
3f38fc2
Change startPeriod
levisingularity Jul 15, 2024
535564d
Merge branch 'master' into feat/mongodb-cluster
levisingularity Jul 15, 2024
133f51f
Fix python library test
levisingularity Jul 15, 2024
4108e09
Update CHANGELOG file
levisingularity Jul 15, 2024
2f3cff0
Fix tests for db cluster
levisingularity Jul 15, 2024
7c9b8a1
Add tests for mongodb cluster
levisingularity Jul 15, 2024
b9c4a8c
Fix filter tags for testing
levisingularity Jul 15, 2024
02dcbcb
Fix config fixtures
levisingularity Jul 15, 2024
5a9f2d6
Fix db mongodb cluster
levisingularity Jul 15, 2024
bc74ff5
fix: upload key
levisingularity Jul 15, 2024
a050920
Fix count mongodb nodes in cluster
levisingularity Jul 15, 2024
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
6 changes: 0 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ jobs:
- name: Runnign integration tests
run: make integration_tests

- name: Installing das-cli package
run: sudo apt -y install $(find . -name *.deb -type f | head -n 1)

- name: Runnign integration tests
run: make integration_tests

tag:
needs:
- integration-tests
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@
[#73] das-cli python-library version is raising an error
[#76] Put version number in openfaas docker image name
[#75] Enable the configuration of a Redis cluster instead of maintaining only a standalone instance
[#87] Configuration of a Mongodb cluster instead of maintaining only a standalone instance
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ man_pages:

integration_tests:
ifdef DAS_CLI_TEST_CLUSTER
@bats tests/integration/*.bats --filter-tags 'redis:cluster'
@bats tests/integration/*.bats --filter-tags 'cluster'
endif

@bats tests/integration/*.bats --filter-tags '!redis:cluster'
@bats tests/integration/*.bats --filter-tags '!cluster'

128 changes: 94 additions & 34 deletions src/commands/config/config_cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from injector import inject
from typing import List, Dict
from common import Settings, StdoutSeverity
from common import (
Command,
Expand All @@ -8,6 +9,7 @@
RemoteContextManager,
get_server_username,
get_public_ip,
get_rand_token,
)


Expand Down Expand Up @@ -41,7 +43,7 @@ class ConfigSet(Command):
redis.container_name
Specifies the name of the Docker container running the Redis server.

redis.custer
redis.cluster
Indicates whether a Redis cluster is being used (true/false).

redis.nodes
Expand Down Expand Up @@ -71,6 +73,24 @@ class ConfigSet(Command):
mongodb.password
The password for connecting to the MongoDB server.

mongodb.cluster
Indicates whether a MongoDB cluster is being used (true/false).

mongodb.cluster_secret_key
This key is uploaded to all nodes within the MongoDB cluster. It is used for mutual authentication between nodes, ensuring that only authorized nodes can communicate with each other.

mongodb.nodes
Receives a list of nodes for MongoDB configuration. For a single-node setup, there must be at least one node specified with the default context. For a cluster setup, there must be at least three nodes specified. Additionally, it is necessary to configure an SSH key and utilize this key on each node to ensure SSH connectivity between them. This is essential because Docker communicates between nodes remotely to deploy images with MongoDB. To establish SSH connectivity, generate an SSH key using `ssh-keygen` and add this key to all servers in the cluster. Ensure that port 22 is open on all servers to allow SSH connections.

mongodb.nodes.[].context
The name of the Docker context containing connection information for the remote Docker instances of other nodes.

mongodb.nodes.[].ip
The IP address of the node.

mongodb.nodes.[].username
The username for connecting to the node.

loader.*
These variables control the Loader settings, responsible for validating and loading meta files into the database, such as:

Expand Down Expand Up @@ -114,19 +134,52 @@ def _set_config(self, config_dict):
else:
self._settings.set(key, value)

def _redis_cluster(self, redis_port) -> list:
def _build_nodes(self, is_cluster: bool, port: int) -> List[Dict]:
nodes = []
server_user = get_server_username()
current_node = {
"context": "default",
"ip": "localhost",
"username": server_user,
}

if is_cluster:
server_public_ip = get_public_ip()

if server_public_ip is None:
raise Exception(
"The server's public ip could not be solved. Make sure it has internet access."
)

current_node["ip"] = server_public_ip

nodes = self._build_cluster(server_user, port)

nodes.insert(
0,
current_node,
)

return nodes

def _build_cluster(
self,
username: str,
port: int,
min_nodes: int = 3,
) -> List[Dict]:
total_nodes = self.prompt(
"Enter the total number of nodes for the redis cluster (>= 3)",
f"Enter the total number of nodes for the cluster (>= {min_nodes})",
hide_input=False,
type=IntRange(3),
type=IntRange(min_nodes),
)

servers = []
for i in range(0, total_nodes - 1):
server_ip = self.prompt(
f"Enter the ip address for the server-{i + 1}",
hide_input=False,
type=ReachableIpAddress(redis_port),
type=ReachableIpAddress(username, port),
)
server_username = self.prompt(
f"Enter the server username for the server-{i + 1}",
Expand All @@ -142,49 +195,30 @@ def _redis_cluster(self, redis_port) -> list:
remote_context_manager = RemoteContextManager(servers)
cluster_contexts = remote_context_manager.create_context()

old_servers = self._settings.get("redis.nodes", [])
remote_context_manager.set_servers(old_servers)
remote_context_manager.remove_context()

return cluster_contexts

def _redis_nodes(self, redis_cluster, redis_port) -> list:
nodes = []
server_user = get_server_username()
redis_current_node = {
"context": "default",
"ip": "localhost",
"username": server_user,
}

if redis_cluster:
server_public_ip = get_public_ip()

if server_public_ip is None:
raise Exception(
"The server's public ip could not be solved. Make sure it has internet access."
)

redis_current_node["ip"] = server_public_ip
def _destroy_contexts(self, servers: List[Dict]):
remote_context_manager = RemoteContextManager(servers)
remote_context_manager.remove_context()

nodes = self._redis_cluster(redis_port)
def _redis_nodes(self, redis_cluster, redis_port) -> List[Dict]:
redis_nodes = self._build_nodes(redis_cluster, redis_port)

nodes.insert(
0,
redis_current_node,
self._destroy_contexts(
servers=self._settings.get("redis.nodes", []),
)

return nodes
return redis_nodes

def _redis(self) -> dict:
def _redis(self) -> Dict:
redis_port = self.prompt(
"Enter Redis port",
default=self._settings.get("redis.port", 6379),
type=int,
)
cluster_default_value = "yes" if self._settings.get("redis.cluster") else "no"
redis_cluster = self.prompt(
"Is it a redis cluster? (yes/no) ",
"Is it a Redis cluster? (yes/no) ",
hide_input=False,
default=cluster_default_value,
type=bool,
Expand All @@ -197,6 +231,15 @@ def _redis(self) -> dict:
"redis.nodes": lambda: self._redis_nodes(redis_cluster, redis_port),
}

def _mongodb_nodes(self, mongodb_cluster, mongodb_port) -> List[Dict]:
mongodb_nodes = self._build_nodes(mongodb_cluster, mongodb_port)

self._destroy_contexts(
servers=self._settings.get("mongodb.nodes", []),
)

return mongodb_nodes

def _mongodb(self) -> dict:
mongodb_port = self.prompt(
"Enter MongoDB port",
Expand All @@ -212,11 +255,28 @@ def _mongodb(self) -> dict:
# hide_input=True, # When hide_input is set I cannot set the answers based on a text file making impossible to test this command
default=self._settings.get("mongodb.password", "admin"),
)
cluster_default_value = "yes" if self._settings.get("mongodb.cluster") else "no"
is_mongodb_cluster = self.prompt(
"Is it a MongoDB cluster? (yes/no) ",
hide_input=False,
default=cluster_default_value,
type=bool,
)
cluster_secret_key = self._settings.get(
"mongodb.cluster_secret_key",
get_rand_token(num_bytes=15),
)
return {
"mongodb.port": mongodb_port,
"mongodb.container_name": f"das-cli-mongodb-{mongodb_port}",
"mongodb.username": mongodb_username,
"mongodb.password": mongodb_password,
"mongodb.cluster": is_mongodb_cluster,
"mongodb.nodes": lambda: self._mongodb_nodes(
is_mongodb_cluster,
mongodb_port,
),
"mongodb.cluster_secret_key": cluster_secret_key,
}

def _loader(self) -> dict:
Expand Down
Loading