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

vdk-server: Wire up external containers (Git, Docker) with the service #194

Merged
merged 4 commits into from
Sep 7, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion projects/vdk-core/plugins/vdk-server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
description="Versatile Data Kit SDK plugin that facilitates the installation of a local Control Service.",
long_description=pathlib.Path("README.md").read_text(),
long_description_content_type="text/markdown",
install_requires=["vdk-core"],
install_requires=["vdk-core", "docker", "kubernetes"],
package_dir={"": "src"},
packages=setuptools.find_namespace_packages(where="src"),
include_package_data=True,
Expand Down
81 changes: 73 additions & 8 deletions projects/vdk-core/plugins/vdk-server/src/taurus/vdk/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import sys
import requests
from kubernetes import client, config, utils
from taurus.vdk.core.errors import BaseVdkError
from taurus.vdk.core.errors import BaseVdkError, ErrorMessage

log = logging.getLogger(__name__)

Expand All @@ -36,12 +36,14 @@ class Installer(object):
git_server_admin_email = "vdkuser@vmware.com"
git_server_repository_name = "vdk-git-repo"

def __init__(self):
self.__current_directory = self.get_current_directory()

def install(self):
"""
Installs all necessary components and configurations.
"""
log.info(f"Starting installation of Versatile Data Kit Control Service")
self.__current_directory = self.get_current_directory()
self.__create_docker_registry_container()
if self.__create_git_server_container():
self.__configure_git_server_with_error_handling()
Expand All @@ -50,6 +52,7 @@ def install(self):
self.__create_kind_cluster()
self.__connect_container_to_kind_network(self.docker_registry_container_name)
self.__connect_container_to_kind_network(self.git_server_container_name)
self.__git_server_ip = self.__resolve_container_ip(self.git_server_container_name)
self.__configure_kind_local_docker_registry()
self.__install_helm_chart()
log.info(f"Versatile Data Kit Control Service installed successfully")
Expand All @@ -63,7 +66,8 @@ def uninstall(self):
self.__delete_git_server_container()
self.__delete_docker_registry_container()

def get_current_directory(self) -> pathlib.Path:
@staticmethod
def get_current_directory() -> pathlib.Path:
return pathlib.Path(__file__).parent.resolve()

def __create_docker_registry_container(self):
Expand Down Expand Up @@ -164,12 +168,44 @@ def __connect_container_to_kind_network(container_name: str):
"""
client = docker.from_env()
try:
# docker network connect "kind" "{container_name}"
client.api.connect_container_to_network(container_name, "kind")
except Exception as ex:
log.info(ex)
finally:
client.close

def __resolve_container_ip(self, container_name):
"""
Returns the IP of the Docker container with the specified name, registered within the 'kind' network.
The IP is obtained by inspecting the configuration of the 'kind' network.
"""
client = docker.from_env()
tpalashki marked this conversation as resolved.
Show resolved Hide resolved
try:
# Find the id of the "kind" network
# docker network ls
networks = client.api.networks()
kind_network = next((n for n in networks if n['Name'] == 'kind'), None)
# Find the "kind" network configuration
# docker network inspect "{kind_net_id}"
kind_network_details = client.api.inspect_network(kind_network['Id'])
# Extract the container's IP
containers = kind_network_details['Containers']
container_id = next((c for c in containers if containers[c]['Name'] == container_name), None)
if container_id:
return self.__remove_ip_subnet_mask(containers[container_id]['IPv4Address'])
tpalashki marked this conversation as resolved.
Show resolved Hide resolved
except Exception as ex:
log.info(ex)
finally:
client.close
tpalashki marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def __remove_ip_subnet_mask(ip: str) -> str:
pos = ip.find('/')
if pos == -1:
return ip
return ip[:pos]

def __configure_git_server_with_error_handling(self):
"""
Configures the Git server at localhost:10080 with the configurations
Expand Down Expand Up @@ -270,7 +306,9 @@ def __transform_file(input_file_name, output_file_name, transformation):
with open(output_file_name, "w") as output_file:
output_file.write(transformed_content)
except IOError as ex:
raise BaseVdkError(f"Failed to transform file {input_file_name} into {output_file_name}. {str(ex)}")
# TODO: fill in what/why/etc for the error message
raise BaseVdkError(
tpalashki marked this conversation as resolved.
Show resolved Hide resolved
ErrorMessage(f"Failed to transform file {input_file_name} into {output_file_name}. {str(ex)}"))

def __transform_template(self, content: str) -> str:
return content.format(docker_registry_name=self.docker_registry_container_name,
Expand Down Expand Up @@ -333,13 +371,40 @@ def __configure_kind_local_docker_registry(self):
log.info(ex)

def __install_helm_chart(self):
"""
Install the VDK Control Service's Helm Chart with all necessary configurations.
"""
try:
# helm repo add vdk-gitlab https://gitlab.com/api/v4/projects/28814611/packages/helm/stable
# helm repo update
# helm install my-release vdk-gitlab/pipelines-control-service
subprocess.run(["helm", "repo", "add", self.helm_repo_local_name, self.helm_repo_url])
subprocess.run(["helm", "repo", "update"])
subprocess.run(["helm", "install", self.helm_installation_name, self.helm_chart_name])
# helm install vdk vdk-gitlab/pipelines-control-service \
# --set deploymentGitUrl=vdk-git-server/vdkuser/vdk-repo.git \
# ...
# Note: The Git server is referenced by IP rather than directly by name; the reason for this
# is that, currently, the Git server name cannot be resolved within the Job Builder container.
# The reason for this is unknown, but is suspected to be related to the Kaniko image that is
# used as a base.
subprocess.run(['helm', 'repo', 'add', self.helm_repo_local_name, self.helm_repo_url])
subprocess.run(['helm', 'repo', 'update'])
subprocess.run(['helm', 'install', self.helm_installation_name, self.helm_chart_name,
# '--wait',
# '--debug',
'--set', 'resources.limits.memory=1G',
'--set', 'cockroachdb.statefulset.replicas=1',
'--set', 'replicas=1',
'--set', 'deploymentBuilderImage.tag=1.2', # TODO: Remove when service adopts 1.2
'--set', 'deploymentGitBranch=master',
'--set', 'deploymentDockerRegistryType=generic',
'--set', f'deploymentDockerRepository={self.docker_registry_container_name}:5000',
'--set', f'proxyRepositoryURL=localhost:5000',
'--set', f'deploymentGitUrl={self.__git_server_ip}/{self.git_server_admin_user}/{self.git_server_repository_name}.git',
'--set', f'deploymentGitUsername={self.git_server_admin_user}',
'--set', f'deploymentGitPassword={self.git_server_admin_password}',
'--set', f'uploadGitReadWriteUsername={self.git_server_admin_user}',
'--set', f'uploadGitReadWritePassword={self.git_server_admin_password}',
'--set', 'extraEnvVars.GIT_SSL_ENABLED=false',
'--set', 'extraEnvVars.DATAJOBS_DEPLOYMENT_BUILDER_EXTRAARGS=--insecure',
])
except Exception as ex:
log.error(f"Failed to install Helm chart. Make sure you have Helm installed. {str(ex)}")

Expand Down