add test_k8s_dashboard_access test steps part1

with the test setup done, this change adds the necessary code to create
a k8s token which will be used to login via the k8s dashboard URL.

Change-Id: I44b3690306f1522c4f2b94af83e2a816f22e9573
Signed-off-by: Gabriel Calixto <Gabriel.CalixtodePaula@windriver.com>
This commit is contained in:
Gabriel Calixto
2025-03-11 16:39:28 -03:00
parent f26b40a315
commit 80a3c82fba
4 changed files with 160 additions and 15 deletions

View File

@@ -4,23 +4,25 @@ from keywords.k8s.k8s_command_wrapper import export_k8s_config
class KubectlFileApplyKeywords(BaseKeyword):
"""_summary_
Args:
BaseKeyword (_type_): _description_
"""
K8s file apply keywords
"""
def __init__(self, ssh_connection: SSHConnection):
"""
Initializes the class with an SSH connection.
Args:
ssh_connection (SSHConnection): An instance of SSHConnection to be used for SSH operations.
"""
self.ssh_connection = ssh_connection
def dashboard_apply_from_yaml(self, yaml_file: str):
def apply_resource_from_yaml(self, yaml_file: str):
"""
Does a dashboard apply using the given yaml file
Applies a Kubernetes resource using the given YAML file.
Args:
yaml_file (): the yaml file to appy
Returns:
yaml_file (str): The path to the YAML file containing the resource definition.
"""
self.ssh_connection.send(export_k8s_config(f"kubectl apply -f {yaml_file}"))
self.validate_success_return_code(self.ssh_connection)

View File

@@ -0,0 +1,60 @@
from framework.logging.automation_logger import get_logger
from framework.ssh.ssh_connection import SSHConnection
from keywords.base_keyword import BaseKeyword
from keywords.k8s.k8s_command_wrapper import export_k8s_config
class KubectlDeleteServiceAccountKeywords(BaseKeyword):
"""
Delete ServiceAccount keywords
"""
def __init__(self, ssh_connection: SSHConnection):
"""
Constructor for KubectlDeleteServiceAccountKeywords.
Args:
ssh_connection (SSHConnection): An SSH connection object used to execute commands on the Kubernetes cluster.
"""
self.ssh_connection = ssh_connection
def delete_serviceaccount(self, serviceaccount_name: str, nspace: str = None) -> str:
"""
Deletes the specified Kubernetes service account.
Args:
serviceaccount_name (str): The name of the service account to delete.
nspace (str, optional): The namespace of the service account. Defaults to None.
Returns:
str: The output of the kubectl delete command.
"""
args = ""
if nspace:
args += f" -n {nspace} "
args += f"{serviceaccount_name}"
output = self.ssh_connection.send(export_k8s_config(f"kubectl delete serviceaccount {args}"))
self.validate_success_return_code(self.ssh_connection)
return output
def cleanup_serviceaccount(self, serviceaccount_name: str, nspace: str = None) -> str:
"""
Deletes a Kubernetes ServiceAccount,method is used for cleanup purposes.
Args:
serviceaccount_name (str): The name of the ServiceAccount to delete.
nspace (str, optional): The namespace of the ServiceAccount. Defaults to None.
Returns:
str: The output of the command.
"""
args = ""
if nspace:
args += f" -n {nspace} "
args += f"{serviceaccount_name}"
self.ssh_connection.send(export_k8s_config(f"kubectl delete serviceaccount {args}"))
rc = self.ssh_connection.get_return_code()
if rc != 0:
get_logger().log_error(f"ServiceAccount {serviceaccount_name} failed to delete")
return rc

View File

@@ -0,0 +1,35 @@
from framework.ssh.ssh_connection import SSHConnection
from keywords.base_keyword import BaseKeyword
from keywords.k8s.k8s_command_wrapper import export_k8s_config
class KubectlCreateTokenKeywords(BaseKeyword):
"""
Keywords for creating a token with kubectl
"""
def __init__(self, ssh_connection: SSHConnection):
"""
Initializes the KubectlCreateTokenKeywords class with an SSH connection.
Args:
ssh_connection (SSHConnection): An object representing the SSH connection.
"""
self.ssh_connection = ssh_connection
def create_token(self, nspace: str, user: str) -> str:
"""
Creates a Kubernetes token for a specified user in a given namespace.
Args:
nspace (str): The Kubernetes namespace where the token will be created.
user (str): The user for whom the token will be created.
Returns:
str: The output from the command execution.
"""
args = f"{user} -n {nspace}"
output = self.ssh_connection.send(export_k8s_config(f"kubectl create token {args}"))
self.validate_success_return_code(self.ssh_connection)
return output

View File

@@ -20,6 +20,8 @@ from keywords.k8s.namespace.kubectl_get_namespaces_keywords import KubectlGetNam
from keywords.k8s.patch.kubectl_apply_patch_keywords import KubectlApplyPatchKeywords
from keywords.k8s.secret.kubectl_create_secret_keywords import KubectlCreateSecretsKeywords
from keywords.k8s.secret.kubectl_delete_secret_keywords import KubectlDeleteSecretsKeywords
from keywords.k8s.serviceaccount.kubectl_delete_serviceaccount_keywords import KubectlDeleteServiceAccountKeywords
from keywords.k8s.token.kubectl_create_token_keywords import KubectlCreateTokenKeywords
from keywords.openssl.openssl_keywords import OpenSSLKeywords
@@ -38,11 +40,12 @@ def check_url_access(url: str) -> tuple:
return req.response.status_code, req.response.text
def copy_k8s_files(ssh_connection: SSHConnection):
def copy_k8s_files(request: fixture, ssh_connection: SSHConnection):
"""
Copy the necessary k8s dashboard yaml files
Args:
request (fixture): pytest fixture
ssh_connection (SSHConnection): ssh connection object
"""
k8s_dashboard_dir = "k8s_dashboard"
@@ -53,6 +56,12 @@ def copy_k8s_files(ssh_connection: SSHConnection):
local_path = get_stx_resource_path(f"resources/cloud_platform/containers/k8s_dashboard/{dashboard_file_name}")
FileKeywords(ssh_connection).upload_file(local_path, f"/home/sysadmin/{k8s_dashboard_dir}/{dashboard_file_name}")
def teardown():
get_logger().log_info("Deleting k8s_dashboard directory")
FileKeywords(ssh_connection).delete_folder_with_sudo(f"/home/sysadmin/{k8s_dashboard_dir}")
request.addfinalizer(teardown)
def create_k8s_dashboard(request: fixture, namespace: str, con_ssh: SSHConnection):
"""
@@ -91,14 +100,12 @@ def create_k8s_dashboard(request: fixture, namespace: str, con_ssh: SSHConnectio
KubectlCreateSecretsKeywords(ssh_connection=con_ssh).create_secret_generic(secret_name=secrets_name, tls_crt=crt, tls_key=key, namespace=namespace)
get_logger().log_info(f"Creating resource from file {k8s_dashboard_file_path}")
KubectlFileApplyKeywords(ssh_connection=con_ssh).dashboard_apply_from_yaml(k8s_dashboard_file_path)
KubectlFileApplyKeywords(ssh_connection=con_ssh).apply_resource_from_yaml(k8s_dashboard_file_path)
def teardown():
KubectlFileDeleteKeywords(ssh_connection=con_ssh).delete_resources(k8s_dashboard_file_path)
# delete created dashboard secret
KubectlDeleteSecretsKeywords(con_ssh).cleanup_secret(namespace=namespace, secret_name=secrets_name)
get_logger().log_info("Deleting k8s_dashboard directory")
con_ssh.send(f"rm -rf {home_k8s}")
get_logger().log_info(f"Updating {name} service to be exposed on port {port}")
arg_port = '{"spec":{"type":"NodePort","ports":[{"port":443, "nodePort": ' + str(port) + "}]}}"
@@ -115,6 +122,44 @@ def create_k8s_dashboard(request: fixture, namespace: str, con_ssh: SSHConnectio
raise KeywordException(detailed_message=f"Kubernetes dashboard returned status code {status_code}")
def get_k8s_token(request: fixture, con_ssh: SSHConnection) -> str:
"""
Get token for login to dashboard.
For Kubernetes versions above 1.24.4, create an admin-user service-account
in the kube-system namespace and bind the cluster-admin ClusterRoleBinding
to this user. Then, create a token for this user in the kube-system namespace.
Args:
request (fixture): pytest fixture
con_ssh (SSHConnection): SSH connection object
Returns:
str: Token for login to the dashboard
"""
get_logger().log_info("Create the admin-user service-account in kube-system and bind the " "cluster-admin ClusterRoleBinding to this user")
adminuserfile = "admin-user.yaml"
serviceaccount = "admin-user"
home_k8s = "/home/sysadmin/k8s_dashboard"
admin_user_file_path = os.path.join(home_k8s, adminuserfile)
get_logger().log_info("Creating the admin-user service-account")
KubectlFileApplyKeywords(ssh_connection=con_ssh).apply_resource_from_yaml(admin_user_file_path)
get_logger().log_info("Creating the token for admin-user")
token = KubectlCreateTokenKeywords(ssh_connection=con_ssh).create_token(nspace="kube-system", user=serviceaccount)
def teardown():
get_logger().log_info(f"Removing serviceaccount {serviceaccount} in kube-system")
KubectlDeleteServiceAccountKeywords(ssh_connection=con_ssh).cleanup_serviceaccount(serviceaccount_name=serviceaccount, nspace="kube-system")
request.addfinalizer(teardown)
get_logger().log_info(f"Token for login to dashboard: {token}")
return token
@mark.p0
def test_k8s_dashboard_access(request):
"""
@@ -139,7 +184,7 @@ def test_k8s_dashboard_access(request):
# Defines dashboard file name, source (local) and destination (remote) file paths.
# Opens an SSH session to active controller.
ssh_connection = LabConnectionKeywords().get_active_controller_ssh()
copy_k8s_files(ssh_connection)
copy_k8s_files(request, ssh_connection)
# Create Dashboard namespace
namespace_name = "kubernetes-dashboard"
kubectl_create_ns_keyword = KubectlCreateNamespacesKeywords(ssh_connection)
@@ -159,3 +204,6 @@ def test_k8s_dashboard_access(request):
# Step 2: Create the necessary k8s dashboard resources
test_namespace = "kubernetes-dashboard"
create_k8s_dashboard(request, namespace=test_namespace, con_ssh=ssh_connection)
# Step 3: Create the token for the dashboard
get_k8s_token(request=request, con_ssh=ssh_connection)