Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

layout schema check #5184

Merged
merged 2 commits into from
Dec 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions contrib/kubespray/quick-start-kubespray.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ CLUSTER_CONFIG="$PWD/config/config.yaml"
echo "layout config file path: ${LAYOUT}"
echo "cluster config file path: ${CLUSTER_CONFIG}"

echo "Checking layout.yaml schema..."
python3 script/validate_layout_schema.py -l ${LAYOUT}

echo "Setting up environment..."
/bin/bash script/environment.sh -c ${CLUSTER_CONFIG} || exit $?

Expand Down
7 changes: 2 additions & 5 deletions contrib/kubespray/script/environment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@ sudo apt-get -y install software-properties-common python3 python3-dev
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
sudo python3 get-pip.py

echo "Install paramiko"
sudo pip3 install paramiko

echo "Install kubernetes package"
sudo pip3 install kubernetes
echo "Install python packages"
sudo pip3 install paramiko kubernetes schema

echo "Install sshpass"
sudo apt-get -y install sshpass
Expand Down
1 change: 0 additions & 1 deletion contrib/kubespray/script/pre-check-generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ def main():

# fill in cpu, memory, computing_device information in both masters and workers
# we assume the layout file the user gives is correct
# TO DO: check layout file before this step
all_machines = masters + workers
for machine in all_machines:
sku_info = layout['machine-sku'][machine['machine-type']]
Expand Down
123 changes: 123 additions & 0 deletions contrib/kubespray/script/validate_layout_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import argparse
import logging
import logging.config
import sys
from schema import Schema, Or, Optional, Regex
import yaml


def setup_logger_config(logger):
"""
Setup logging configuration.
"""
if len(logger.handlers) == 0:
logger.propagate = False
logger.setLevel(logging.DEBUG)
consoleHandler = logging.StreamHandler()
consoleHandler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s [%(levelname)s] - %(filename)s:%(lineno)s : %(message)s')
consoleHandler.setFormatter(formatter)
logger.addHandler(consoleHandler)

logger = logging.getLogger(__name__)
setup_logger_config(logger)


def load_yaml_config(config_path):
with open(config_path, "r") as f:
config_data = yaml.load(f, yaml.SafeLoader)
return config_data


def validate_layout_schema(layout):
schema = Schema(
{
'machine-sku': {
str: {
'mem': str,
'cpu': {
'vcore': int,
},
Optional('computing-device'): {
'type': str,
'model': str,
'count': int,
}
}
},
'machine-list': [
{
# https://github.com/kubernetes-sigs/kubespray/blob/release-2.11/roles/kubernetes/preinstall/tasks/0020-verify-settings.yml#L124
'hostname': Regex(r"^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"),
'hostip': Regex(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$"),
'machine-type': str,
Optional('pai-master'): Or('true', 'false'),
Optional('pai-worker'): Or('true', 'false'),
Optional('pai-storage'): Or('true', 'false'),
}
]
}
)
return schema.validate(layout)


def check_layout(layout):
# hostname / hostip should be unique
hostnames = [elem['hostname'] for elem in layout['machine-list']]
if len(hostnames) != len(set(hostnames)):
logger.error("hostname should be unique")
return False
hostips = [elem['hostip'] for elem in layout['machine-list']]
if len(hostips) != len(set(hostips)):
logger.error("hostip should be unique")
return False

# machine-type should be defined in machine-sku
for machine in layout['machine-list']:
if machine['machine-type'] not in layout['machine-sku']:
logger.error("machine-type {} is not defined".format(machine['machine-type']))
return False

masters = list(filter(lambda elem: 'pai-master' in elem and elem["pai-master"] == 'true', layout['machine-list']))
workers = list(filter(lambda elem: 'pai-worker' in elem and elem["pai-worker"] == 'true', layout['machine-list']))
# only one pai-master
if len(masters) == 0:
logger.error('No master machine specified.')
return False
if len(masters) > 1:
logger.error('More than one master machine specified.')
return False
# at least one pai-worker
if len(workers) == 0:
logger.error('No worker machine specified.')
return False
# pai-master / pai-worker cannot be true at the same time
if 'pai-worker' in masters[0] and masters[0]['pai-worker'] == 'true':
logger.error("One machine can not be pai-master and pai-worker at the same time.")
return False

suiguoxin marked this conversation as resolved.
Show resolved Hide resolved
return True


def main():
parser = argparse.ArgumentParser()
parser.add_argument('-l', '--layout', dest="layout", required=True,
help="layout.yaml")
args = parser.parse_args()

layout = load_yaml_config(args.layout)
try:
validate_layout_schema(layout)
except Exception as exp:
logger.error("layout.yaml schema validation failed: \n %s", exp)
sys.exit(1)

if not check_layout(layout):
logger.error("layout.yaml schema validation failed")
sys.exit(1)

logger.info("layout.yaml schema validation succeeded.")


if __name__ == "__main__":
main()