From 353aeb5fc375f6b93d865ce2a4a9ff0e8428e097 Mon Sep 17 00:00:00 2001 From: garciadeblas Date: Thu, 13 Feb 2025 10:23:34 +0100 Subject: [PATCH] Feature 10923: Advanced cluster management Change-Id: I384d1d3f6263876650681ed4d3b96709f08f45d8 Signed-off-by: garciadeblas --- README.md | 1 + .../lib/advanced_cluster_mgmt_lib.resource | 240 ++++++++++++++++++ ...itops_01-advanced_cluster_management.robot | 112 ++++++++ 3 files changed, 353 insertions(+) create mode 100644 robot-systest/lib/advanced_cluster_mgmt_lib.resource create mode 100644 robot-systest/testsuite/gitops_01-advanced_cluster_management.robot diff --git a/README.md b/README.md index 1c32dcb..45f7424 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,7 @@ The following tags exist for each testsuite: - `cluster_slices`: `slice_01`, `slice_02` - `cluster_heal`: `heal_01`, `heal_02`, `heal_03`, `heal_04` - `cluster_osm_rest`: `sol003_01` + - `cluster_gitops`: `gitops_01` - daily: for all testsuites that will run in the daily job - regression: for all testsuites that should pass in the current stable branch - sanity: for all testsuites that should be passed by each commit in the diff --git a/robot-systest/lib/advanced_cluster_mgmt_lib.resource b/robot-systest/lib/advanced_cluster_mgmt_lib.resource new file mode 100644 index 0000000..de9bb5d --- /dev/null +++ b/robot-systest/lib/advanced_cluster_mgmt_lib.resource @@ -0,0 +1,240 @@ +*** Comments *** +# Copyright 2020 Canonical Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +*** Settings *** +Documentation Library providing keywords for CRUD operations over clusters, +... OKAs and KSUs with OSM client. +Library OperatingSystem +Library String + + +*** Variables *** +${SUCCESS_RETURN_CODE} 0 +${CLUSTER_LAUNCH_MAX_WAIT_TIME} 12min +${CLUSTER_LAUNCH_POL_TIME} 30sec +${CLUSTER_DELETE_MAX_WAIT_TIME} 12min +${CLUSTER_DELETE_POL_TIME} 30sec +${OKA_OPERATION_MAX_WAIT_TIME} 5min +${OKA_OPERATION_POL_TIME} 15sec +${KSU_CREATION_MAX_WAIT_TIME} 10min +${KSU_CREATION_POL_TIME} 30sec +${KSU_DELETION_MAX_WAIT_TIME} 7min +${KSU_DELETION_POL_TIME} 15sec + + +*** Keywords *** +Create Cluster + [Documentation] Create a Kubernetes cluster in OSM using the name, version, nodes, etc., passed as arguments. + [Arguments] ${name} ${vim_account} ${description} ${vm_size} ${version} ${nodes} ${region} ${resource_group} ${wait_flag}=True + ${command}= Catenate + ... osm cluster-create ${name} + ... --node-count ${nodes} + ... --node-size ${vm_size} + ... --version ${version} + ... --vim-account ${vim_account} + ... --description ${description} + ... --region-name ${region} + ... --resource-group ${resource_group} + ${rc} ${stdout}= Run And Return Rc And Output ${command} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=Cluster creation failed: ${stdout} + ${cluster_id}= Set Variable ${stdout} + Log ${cluster_id} + Check Cluster Age Keys ${cluster_id} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${CLUSTER_LAUNCH_MAX_WAIT_TIME} ${CLUSTER_LAUNCH_POL_TIME} + ... Check For Cluster To Be Ready ${name} + END + RETURN ${cluster_id} + +Check Cluster Age Keys + [Documentation] Check AGE keys in the cluster + [Arguments] ${cluster_name} + ${rc} ${stdout}= Run And Return Rc And Output + ... osm cluster-show ${cluster_name} -o jsonpath='{.age_privkey}' + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + # TODO: Check if privkey contains the expected value + Log privkey is ${stdout} + ${rc} ${stdout}= Run And Return Rc And Output + ... osm cluster-show ${cluster_name} -o jsonpath='{.age_pubkey}' + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + # TODO: Check if pubkey contains the expected value + Log pubkey is ${stdout} + +Delete Cluster + [Documentation] Unregister/delete a Kubernetes cluster from OSM. + [Arguments] ${cluster_name} ${wait_flag}=True + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-delete ${cluster_name} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=Cluster deletion failed: ${stdout} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${CLUSTER_DELETE_MAX_WAIT_TIME} ${CLUSTER_DELETE_POL_TIME} + ... Check For Cluster Deletion Status ${cluster_name} + END + +Check For Cluster Deletion Status + [Documentation] Check if a Kubernetes cluster identified by name is deleted or in error state. + [Arguments] ${cluster_name} + ${rc} ${output}= Run And Return Rc And Output osm cluster-show ${cluster_name} + Log ${rc},${output} + ${rc} ${resourceState}= Run And Return Rc And Output osm cluster-show ${cluster_name} -o jsonpath='{.resourceState}' + Log ${rc},${resourceState} + IF '$rc' == '$SUCCESS_RETURN_CODE' and '$resourceState' == 'ERROR' + Fail Cluster is in error state and will not be deleted. + ELSE + Log Either the cluster ${cluster_name} has been deleted or it is in a valid state. + Check For Cluster To Be Deleted ${cluster_name} + END + +Get Clusters + [Documentation] Get the list of Kubernetes clusters in OSM, and return it. + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-list + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + Log ${stdout} + RETURN ${stdout} + +Check For Cluster To Be Ready + [Documentation] Check if a Kubernetes cluster is ready (the resourceState must be READY). + [Arguments] ${cluster_name} + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-show ${cluster_name} + Log ${rc},${stdout} + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-show ${cluster_name} -o jsonpath='{.resourceState}' + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + Should Be Equal As Strings ${stdout} READY + +Check For Cluster To Be Deleted + [Documentation] Check if a Kubernetes cluster identified by name is not present in OSM. + [Arguments] ${cluster_name} + ${matches}= Get Regexp Matches ${cluster_name} ^[0-9a-fA-F-]{36}$ + Log ${matches} + IF ${matches} != @{EMPTY} + Log ${cluster_name} is a valid UUID + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-list --filter _id="${cluster_name}" | grep ${cluster_name} + ELSE + Log ${cluster_name} is not a valid UUID, so it will be treated as a name + ${rc} ${stdout}= Run And Return Rc And Output osm cluster-list --filter name="${cluster_name}" | grep ${cluster_name} + END + Log ${rc},${stdout} + Should Be Empty ${stdout} + +Add OKA Package + [Documentation] Add OKA package to OSM + [Arguments] ${oka_name} ${oka_folder} ${oka_profile} ${wait_flag}=True + ${rc} ${stdout}= Run And Return Rc And Output + ... osm oka-add ${oka_name} ${oka_folder} --description ${oka_name} --profile-type ${oka_profile} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=OKA addition failed: ${stdout} + ${oka_id}= Set Variable ${stdout} + Log ${oka_id} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${OKA_OPERATION_MAX_WAIT_TIME} ${OKA_OPERATION_POL_TIME} + ... Check For OKA To Be Ready ${oka_id} + END + RETURN ${oka_id} + +Delete OKA Package + [Documentation] Delete OKA package from OSM + [Arguments] ${oka_name} ${wait_flag}=True + ${rc} ${stdout}= Run And Return Rc And Output + ... osm oka-delete ${oka_name} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=OKA deletion failed: ${stdout} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${OKA_OPERATION_MAX_WAIT_TIME} ${OKA_OPERATION_POL_TIME} + ... Check For OKA To Be Deleted ${oka_name} + END + +Check For OKA To Be Ready + [Documentation] Check if an OKA is ready (the resourceState must be READY). + [Arguments] ${oka_name} + ${rc} ${stdout}= Run And Return Rc And Output osm oka-show ${oka_name} + Log ${rc},${stdout} + ${rc} ${stdout}= Run And Return Rc And Output osm oka-show ${oka_name} -o jsonpath='{.resourceState}' + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + Should Be Equal As Strings ${stdout} READY + +Check For OKA To Be Deleted + [Documentation] Check if an OKA identified by oka_name is not present in OSM. + [Arguments] ${oka_name} + ${rc} ${output}= Run And Return Rc And Output osm oka-show ${oka_name} + Log ${rc},${output} + ${matches}= Get Regexp Matches ${oka_name} ^[0-9a-fA-F-]{36}$ + Log ${matches} + IF ${matches} != @{EMPTY} + Log ${oka_name} is a valid UUID + ${rc} ${stdout}= Run And Return Rc And Output osm oka-list --filter _id="${oka_name}" | grep ${oka_name} + ELSE + Log ${oka_name} is not a valid UUID, so it will be treated as a name + ${rc} ${stdout}= Run And Return Rc And Output osm oka-list --filter name="${oka_name}" | grep ${oka_name} + END + Log ${rc},${stdout} + Should Be Empty ${stdout} + +Create KSU + [Documentation] Create a KSU + [Arguments] ${ksu_name} ${ksu_description} ${profile} ${profile_type} ${oka_name} ${ksu_params_file} ${wait_flag}=True + ${rc} ${stdout}= Run And Return Rc And Output + ... osm ksu-create --ksu ${ksu_name} --description ${ksu_description} --profile ${profile} --profile-type ${profile_type} --oka ${oka_name} --params ${ksu_params_file} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=KSU creation failed: ${stdout} + ${ksu_id}= Set Variable ${stdout} + Log ${ksu_id} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${KSU_CREATION_MAX_WAIT_TIME} ${KSU_CREATION_POL_TIME} + ... Check For KSU To Be Ready ${ksu_id} + END + RETURN ${ksu_id} + +Delete KSU + [Documentation] Delete KSU from OSM + [Arguments] ${ksu_name} ${wait_flag}=True + ${rc} ${stdout}= Run And Return Rc And Output + ... osm ksu-delete ${ksu_name} + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} msg=KSU deletion failed: ${stdout} + IF ${wait_flag} == True + Wait Until Keyword Succeeds ${KSU_DELETION_MAX_WAIT_TIME} ${KSU_DELETION_POL_TIME} + ... Check For KSU To Be Deleted ${ksu_name} + END + +Check For KSU To Be Ready + [Documentation] Check if a KSU is ready (the resourceState must be READY). + [Arguments] ${ksu_name} + ${rc} ${stdout}= Run And Return Rc And Output osm ksu-show ${ksu_name} + Log ${rc},${stdout} + ${rc} ${stdout}= Run And Return Rc And Output osm ksu-show ${ksu_name} -o jsonpath='{.resourceState}' + Log ${rc},${stdout} + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + Should Be Equal As Strings ${stdout} READY + +Check For KSU To Be Deleted + [Documentation] Check if a KSU identified by ksu_name is not present in OSM. + [Arguments] ${ksu_name} + ${rc} ${output}= Run And Return Rc And Output osm ksu-show ${ksu_name} + Log ${rc},${output} + ${matches}= Get Regexp Matches ${ksu_name} ^[0-9a-fA-F-]{36}$ + Log ${matches} + IF ${matches} != @{EMPTY} + Log ${ksu_name} is a valid UUID + ${rc} ${stdout}= Run And Return Rc And Output osm ksu-list --filter _id="${ksu_name}" | grep ${ksu_name} + ELSE + Log ${ksu_name} is not a valid UUID, so it will be treated as a name + ${rc} ${stdout}= Run And Return Rc And Output osm ksu-list --filter name="${ksu_name}" | grep ${ksu_name} + END + Log ${rc},${stdout} + Should Be Empty ${stdout} diff --git a/robot-systest/testsuite/gitops_01-advanced_cluster_management.robot b/robot-systest/testsuite/gitops_01-advanced_cluster_management.robot new file mode 100644 index 0000000..e308a58 --- /dev/null +++ b/robot-systest/testsuite/gitops_01-advanced_cluster_management.robot @@ -0,0 +1,112 @@ +*** Comments *** +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +*** Settings *** +Documentation [GITOPS-01] Advanced Cluster Management. + +Library OperatingSystem +Library String +Library Collections +Library Process + +Resource ../lib/advanced_cluster_mgmt_lib.resource + +Test Tags gitops_01 cluster_gitops + +Suite Teardown Run Keyword And Ignore Error Suite Cleanup + + +*** Variables *** +# OKA packages +${OKA_FOLDER} '%{PACKAGES_FOLDER}/oka' +${OKA_PKG1} apps/testapp +${OKA_NAME1} testapp +${OKA_PROFILE1} app-profile +${OKA_PKG2} apps/testacme +${OKA_NAME2} testacme +${OKA_PROFILE2} app-profile +${OKA_PKG3} apps/jenkins +${OKA_NAME3} jenkins +${OKA_PROFILE3} app-profile + +# Cluster +${CLUSTER_NAME} gitops01 +${CLUSTER_DESCRIPTION} "Cluster for gitops01 Robot test suite" +${CLUSTER_VM_SIZE} Standard_D2_v2 +${CLUSTER_NODES} 2 +${REGION_NAME} northeurope +${RESOURCE_GROUP} OSM-CTIO +${KUBERNETES_VERSION} "1.30" + +# KSUs +${KSU_NAME1} testapp +${KSU_NAME2} testacme +${KSU_NAME3} jenkins + + +*** Test Cases *** +Add OKA Packages For The Testsuite + [Documentation] Add OKA packages for the testsuite. + [Tags] oka create + Add OKA Package ${OKA_NAME1} '${OKA_FOLDER}/${OKA_PKG1}' ${OKA_PROFILE1} + Add OKA Package ${OKA_NAME2} '${OKA_FOLDER}/${OKA_PKG2}' ${OKA_PROFILE2} + Add OKA Package ${OKA_NAME3} '${OKA_FOLDER}/${OKA_PKG3}' ${OKA_PROFILE3} + +Create Cluster For Testsuite in Azure + [Documentation] Create K8s cluster for the testsuite. + [Tags] cluster create + ${id}= Create Cluster ${CLUSTER_NAME} %{VIM_TARGET} ${CLUSTER_DESCRIPTION} ${CLUSTER_VM_SIZE} ${KUBERNETES_VERSION} ${CLUSTER_NODES} ${REGION_NAME} ${RESOURCE_GROUP} + Set Suite Variable ${CLUSTER_ID} ${id} + Log ${CLUSTER_ID} + +Get Cluster Kubeconfig + [Documentation] Get Kubeconfig for the cluster. + [Tags] cluster + ${rc} ${stdout}= Run And Return Rc And Output + ... osm cluster-show ${CLUSTER_NAME} -o jsonpath='{.credentials}' | yq -y + Should Be Equal As Integers ${rc} ${SUCCESS_RETURN_CODE} + Log ${stdout} + +Create KSU3 + [Documentation] Create KSU3 based on ${OKA_NAME3} with params. + [Tags] ksu create + ${id}= Create KSU ${KSU_NAME3} ${KSU_NAME3} ${CLUSTER_NAME} app-profile ${OKA_NAME3} ${OKA_FOLDER}/apps/jenkins-params.yaml + Set Suite Variable ${KSU_ID3} ${id} + Log ${KSU_ID3} + +Delete KSU3 + [Documentation] Delete KSU3 based on ${OKA_NAME3}. + [Tags] cleanup ksu + Delete KSU ${KSU_ID3} + +Delete Cluster For Testsuite + [Documentation] Delete K8s cluster for the testsuite. + [Tags] cleanup cluster + Delete Cluster ${CLUSTER_NAME} + +Delete OKA Packages For The Testsuite + [Documentation] Delete OKA packages for the testsuite. + [Tags] cleanup oka + Delete OKA Package ${OKA_NAME1} + Delete OKA Package ${OKA_NAME2} + Delete OKA Package ${OKA_NAME3} + + +*** Keywords *** +Suite Cleanup + [Documentation] Test Suit Cleanup: Deleting cluster, KSUs, OKAs + Run Keyword If Any Tests Failed Delete Cluster ${CLUSTER_NAME} + Run Keyword If Any Tests Failed Delete OKA Package ${OKA_NAME1} + Run Keyword If Any Tests Failed Delete OKA Package ${OKA_NAME2} + Run Keyword If Any Tests Failed Delete OKA Package ${OKA_NAME3} -- 2.25.1