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

Commit

Permalink
check layout.yaml schema before k8s installation (#5184)
Browse files Browse the repository at this point in the history
  • Loading branch information
suiguoxin authored Dec 21, 2020
1 parent 86c73e3 commit c24872b
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
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

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()

0 comments on commit c24872b

Please sign in to comment.