*** 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_REGISTER_MAX_WAIT_TIME}   7min
${CLUSTER_REGISTER_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}   7min
${KSU_CREATION_POL_TIME}   30sec
${KSU_DELETION_MAX_WAIT_TIME}   5min
${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_REGISTER_MAX_WAIT_TIME}   ${CLUSTER_REGISTER_POL_TIME}
        ...   Check For Cluster To Be Ready   ${name}
    END
    RETURN   ${cluster_id}

Register Cluster
    [Documentation]   Register a Kubernetes cluster in OSM using a provided name and kubeconfig credentials.
    [Arguments]   ${name}   ${vim_account}   ${creds}   ${description}   ${bootstrap_flag}=True   ${wait_flag}=True
    ${command}=   Catenate
    ...   osm cluster-register ${name}
    ...   --vim-account ${vim_account}
    ...   --creds ${creds}
    ...   --description ${description}
    IF   ${bootstrap_flag} == True
        Catenate   ${command}   --bootstrap
    ELSE
        Catenate   ${command}   --no-bootstrap
    END
    ${rc}   ${stdout}=   Run And Return Rc And Output   ${command}
    Log   ${rc},${stdout}
    Should Be Equal As Integers   ${rc}   ${SUCCESS_RETURN_CODE}   msg=Cluster registration 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]   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

Deregister Cluster
    [Documentation]   Deregister a Kubernetes cluster from OSM.
    [Arguments]   ${cluster_name}   ${wait_flag}=True
    ${rc}   ${stdout}=   Run And Return Rc And Output   osm cluster-deregister ${cluster_name}
    Log   ${rc},${stdout}
    Should Be Equal As Integers   ${rc}   ${SUCCESS_RETURN_CODE}   msg=Cluster deregistration 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}
        ${rc}   ${stdout}=   Run And Return Rc And Output   osm cluster-list --filter _id="${cluster_name}" -o jsonpath='[*]._id'| grep -E "\^${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}
        ${rc}   ${stdout}=   Run And Return Rc And Output   osm cluster-list --filter name="${cluster_name}" -o jsonpath='[*].name'| grep -E "\^${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}
        ${rc}   ${stdout}=   Run And Return Rc And Output   osm oka-list --filter _id="${oka_name}" -o jsonpath='[*]._id'| grep -E "\^${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}
        ${rc}   ${stdout}=   Run And Return Rc And Output   osm oka-list --filter name="${oka_name}" -o jsonpath='[*].name'| grep -E "\^${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}=${EMPTY}   ${wait_flag}=True
    IF   "${ksu_params_file}" != "${EMPTY}"
        ${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}
    ELSE
        ${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}
    END
    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}
       ${rc}   ${stdout}=   Run And Return Rc And Output   osm ksu-list --filter _id="${ksu_name}" -o jsonpath='[*]._id'| grep -E "\^${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}
       ${rc}   ${stdout}=   Run And Return Rc And Output   osm ksu-list --filter name="${ksu_name}" -o jsonpath='[*].name'| grep -E "\^${ksu_name}\$"
    END
    Log   ${rc},${stdout}
    Should Be Empty   ${stdout}
