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

Add support for private registry on Megalos #282

Merged
Show file tree
Hide file tree
Changes from 1 commit
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
37 changes: 37 additions & 0 deletions src/Kathara/cli/ui/setting/KubernetesOptionsHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,44 @@ def add_items(self, current_menu: ConsoleMenu, menu_formatter: MenuFormatBuilder

image_pull_policy_item = SubmenuItem(image_pull_policy_string, image_pull_policy_menu, current_menu)

# Private Registry dockerconfigjson Option
pr_dcj_string = "Private Registry Docker Configuration"
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved
pr_dcj_menu = SelectionMenu(
strings=[],
title=pr_dcj_string,
prologue_text="""Add a base64-encoded Docker configuration string to """
"""access private container registries. It will be used """
"""to create a Kubernetes secret of type `kubernetes.io/dockerconfigjson`.

Default is %s.""" % DEFAULTS['private_registry_dockerconfigjson'],
formatter=menu_formatter
)

pr_dcj_menu.append_item(
FunctionItem(
text=pr_dcj_string,
function=setting_utils.read_value,
args=['private_registry_dockerconfigjson',
RegexValidator(r'.*'),
'Write a base64-encoded Docker configuration string:',
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved
'Docker configuration string not valid!'
],
should_exit=True
)
)
pr_dcj_menu.append_item(
FunctionItem(
text="Reset value to Empty String",
function=setting_utils.update_setting_value,
args=["private_registry_dockerconfigjson", None],
should_exit=True
)
)

pr_dcj_item = SubmenuItem(pr_dcj_string, pr_dcj_menu, current_menu)

current_menu.append_item(api_url_item)
current_menu.append_item(api_token_item)
current_menu.append_item(host_shared_item)
current_menu.append_item(image_pull_policy_item)
current_menu.append_item(pr_dcj_item)
8 changes: 7 additions & 1 deletion src/Kathara/manager/kubernetes/KubernetesMachine.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,11 +458,17 @@ def _build_definition(self, machine: Machine, config_map: client.V1ConfigMap) ->
)
))

# Add image_pull_secrets if using a private registry
image_pull_secrets_arg = {}
if Setting.get_instance().private_registry_dockerconfigjson:
image_pull_secrets_arg = {"image_pull_secrets": [client.V1LocalObjectReference(name="private-registry")]}
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved

pod_spec = client.V1PodSpec(containers=[container_definition],
hostname=machine.meta['real_name'],
dns_policy="None",
dns_config=dns_config,
volumes=volumes
volumes=volumes,
**image_pull_secrets_arg
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved
)

pod_template = client.V1PodTemplateSpec(metadata=pod_metadata, spec=pod_spec)
Expand Down
25 changes: 25 additions & 0 deletions src/Kathara/manager/kubernetes/KubernetesNamespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from kubernetes.client.api import core_v1_api
from kubernetes.client.rest import ApiException

from ...setting.Setting import Setting
from ...model.Lab import Lab


Expand Down Expand Up @@ -32,6 +33,9 @@ def create(self, lab: Lab) -> Optional[client.V1Namespace]:
try:
self.client.create_namespace(namespace_definition)
self._wait_namespace_creation(lab.hash)
pr_dcj = Setting.get_instance().private_registry_dockerconfigjson
if pr_dcj:
self._create_private_registry_secret(lab.hash, pr_dcj)
except ApiException:
return None

Expand Down Expand Up @@ -80,6 +84,27 @@ def get_namespace(self, lab_hash: str) -> Optional[client.V1Namespace]:
namespace = self.client.list_namespace(label_selector=f"kubernetes.io/metadata.name={lab_hash}").items
return namespace.pop() if namespace else None


def _create_private_registry_secret(self, lab_hash: str, pr_dcj: str) -> None:
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved
"""Create a kubernetes.io/dockerconfigjson secret for allowing access to private registries.

Args:
lab_hash (str): The name of the Kubernetes Namespace to add the secret to.
pr_dcj (str): The private registry dockerconfigjson.

Returns:
None
"""
secret_definition = client.V1Secret(
api_version="v1",
kind="Secret",
metadata=client.V1ObjectMeta(name="private-registry", namespace=lab_hash),
type="kubernetes.io/dockerconfigjson",
data={".dockerconfigjson": pr_dcj}
)

self.client.create_namespaced_secret(lab_hash, secret_definition)

def _wait_namespace_creation(self, lab_hash: str) -> None:
"""Wait the creation of the specified Kubernetes Namespace. Returns when the namespace becomes `Active`.

Expand Down
9 changes: 6 additions & 3 deletions src/Kathara/setting/addon/KubernetesSettingsAddon.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@
"api_server_url": "Empty String",
"api_token": "Empty String",
"host_shared": True,
"image_pull_policy": "IfNotPresent"
"image_pull_policy": "IfNotPresent",
"private_registry_dockerconfigjson": "Empty String"
GioBar00 marked this conversation as resolved.
Show resolved Hide resolved
}


class KubernetesSettingsAddon(SettingsAddon):
__slots__ = ['api_server_url', 'api_token', 'host_shared', 'image_pull_policy']
__slots__ = ['api_server_url', 'api_token', 'host_shared', 'image_pull_policy', 'private_registry_dockerconfigjson']

def __init__(self) -> None:
self.api_server_url: Optional[str] = None
self.api_token: Optional[str] = None
self.host_shared: bool = True
self.image_pull_policy: Optional[str] = "IfNotPresent"
self.private_registry_dockerconfigjson: Optional[str] = None

def _to_dict(self) -> Dict[str, Any]:
return {
'api_server_url': self.api_server_url,
'api_token': self.api_token,
'host_shared': self.host_shared,
'image_pull_policy': self.image_pull_policy
'image_pull_policy': self.image_pull_policy,
'private_registry_dockerconfigjson': self.private_registry_dockerconfigjson
}