From b5d0f8d200c2ac7a5e8980890cdbc32786b449b5 Mon Sep 17 00:00:00 2001 From: Michael Maximilien Date: Tue, 28 Jan 2025 18:32:10 -0800 Subject: [PATCH] [DRAFT] first PR for validate command and includes the Python CLI structure. Eventually fixes issue #132 --- beeAI | 3 ++ common/common.py | 62 +++++++++++++++++++++++++++++++ test/schema/funnier_workflow.yml | 6 +-- test/schema/validator.py | 23 ------------ tools/cli/beeAI.py | 43 ++++++++++++++++++++++ tools/cli/cli.py | 63 ++++++++++++++++++++++++++++++++ tools/cli/validate_command.py | 42 +++++++++++++++++++++ 7 files changed, 216 insertions(+), 26 deletions(-) create mode 100755 beeAI create mode 100644 common/common.py delete mode 100644 test/schema/validator.py create mode 100755 tools/cli/beeAI.py create mode 100644 tools/cli/cli.py create mode 100644 tools/cli/validate_command.py diff --git a/beeAI b/beeAI new file mode 100755 index 0000000..2c230eb --- /dev/null +++ b/beeAI @@ -0,0 +1,3 @@ +#!/bin/bash + +python3 ./tools/cli/cli.py $@ \ No newline at end of file diff --git a/common/common.py b/common/common.py new file mode 100644 index 0000000..3f32006 --- /dev/null +++ b/common/common.py @@ -0,0 +1,62 @@ +# Copyright © 2025 IBM +# +# 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. + +import sys +from random import randint + +VERBOSE=False + +class Colors: + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +class Console: + def verbose(msg): + if VERBOSE: + print(f"{Colors.OKBLUE}{msg}{Colors.ENDC}".format(msg=str(msg))) + + def print(msg=''): + print(msg) + + def println(no=1): + for i in range(no): + print() + + def ok(msg): + print(f"{Colors.OKGREEN}{msg}{Colors.ENDC}".format(msg=str(msg))) + + def error(msg): + Console.fail(msg) + + def fail(msg): + print(f"{Colors.FAIL}Error: {msg}{Colors.ENDC}".format(msg=str(msg))) + + def warn(msg): + print(f"{Colors.WARNING}Warning: {msg}{Colors.ENDC}".format(msg=str(msg))) + + def progress(count, total, status=''): + bar_len = 60 + filled_len = int(round(bar_len * count / float(total))) + + percents = round(100.0 * count / float(total), 1) + bar = '=' * filled_len + '-' * (bar_len - filled_len) + + sys.stdout.write('[%s] %s%s ...%s\r' % (bar, percents, '%', status)) + sys.stdout.flush() \ No newline at end of file diff --git a/test/schema/funnier_workflow.yml b/test/schema/funnier_workflow.yml index f863d0b..e5d0f2c 100644 --- a/test/schema/funnier_workflow.yml +++ b/test/schema/funnier_workflow.yml @@ -26,6 +26,6 @@ spec: - name: colleague agent: colleague condition: - - if: { input.find('funnier') != -1 } - then: expert - else: end \ No newline at end of file + - if: (input.find('funnier') != -1) + then: expert + else: end diff --git a/test/schema/validator.py b/test/schema/validator.py deleted file mode 100644 index 924eb47..0000000 --- a/test/schema/validator.py +++ /dev/null @@ -1,23 +0,0 @@ -import sys -import yaml -import json -import jsonschema - -def validate_yaml(yaml_file, schema_file): - with open(schema_file, 'r') as f: - schema = json.load(f) - print(schema) - - with open(yaml_file, 'r') as f: - yamls = yaml.safe_load_all(f) - for yaml_data in yamls: - json_data = json.dumps(yaml_data, indent=4) - print(json_data) - jsonschema.validate(yaml_data, schema) - print("YAML file is valid.") - -if __name__ == "__main__": - if len(sys.argv) != 3: - print("Usage: python validate.py yamlfile schemafile") - else: - validate_yaml(sys.argv[1], sys.argv[2]) diff --git a/tools/cli/beeAI.py b/tools/cli/beeAI.py new file mode 100755 index 0000000..6b22a31 --- /dev/null +++ b/tools/cli/beeAI.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +# Copyright © 2025 IBM +# +# 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. + +"""BeeAI + +Usage: + beeAI validate SCHEMA_FILE YAML_FILE [options] + + beeAI (-h | --help) + beeAI (-v | --version) + +Options: + --verbose Show all output. + + -h --help Show this screen. + -v --version Show version. + +""" +import os, sys, traceback + +from docopt import docopt +from cli import * + +if __name__ == '__main__': + args = docopt(__doc__, version='beeAI CLI v0.0.0') + command = CLI(args).command() + rc = command.execute() + if rc != 0: + Console.error("executing command: {rc}".format(rc=rc)) + sys.exit(rc) diff --git a/tools/cli/cli.py b/tools/cli/cli.py new file mode 100644 index 0000000..b318a93 --- /dev/null +++ b/tools/cli/cli.py @@ -0,0 +1,63 @@ +# Copyright © 2025 IBM +# +# 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. + +import io, sys + +from common import * + +class CLI: + def __init__(self, args): + self.args = args + if self.args['--verbose']: + VERBOSE = True + + def command(self): + if self.args.get('validate') and self.args['validate']: + return Validate(self.args) + else: + raise Exception("Invalid command") + +class Command: + def __init__(self, args, credentials, client): + self.__init_empty_options(args) + self.args = args + + def println(self, msg): + self.print(msg + "\n") + + def print(self, msg): + Console.print(msg) + + def warn(self, msg): + Console.warn(msg) + + def verbose(self): + return self.args['--verbose'] + + def execute(self): + func = self.dispatch() + rc = func() + if rc == None: + return 0 + else: + if isinstance(rc, int): + return rc + else: + return 1 + + def dispatch(self): + if self.args['validate']: + return self.validate + else: + raise Exception("Invalid subcommand") diff --git a/tools/cli/validate_command.py b/tools/cli/validate_command.py new file mode 100644 index 0000000..0a4e5a6 --- /dev/null +++ b/tools/cli/validate_command.py @@ -0,0 +1,42 @@ +# Copyright © 2025 IBM +# +# 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. + +import io, sys, yaml, json, jsonschema + +# validate command group +class Validate(Command): + def __init__(self, args): + self.args = args + super().__init__(self.args) + + def SCHEMA_FILE(self): + return self.args['SCHEMA_FILE'] + + def YAML_FILE(self): + return self.args['SCHEMA_FILE'] + + def name(self): + return "validate" + + def validate(self): + Console.print("validate {yaml_file} with schema {schema_file}".format(yaml_file=self.YAML_FILE, schema_file=self.SCHEMA_FILE)) + with open(self.SCHEMA_FILE, 'r') as f: + schema = json.load(f) + with open(self.YAML_FILE, 'r') as f: + yamls = yaml.safe_load_all(f) + for yaml_data in yamls: + json_data = json.dumps(yaml_data, indent=4) + jsonschema.validate(yaml_data, schema) + Console.print("YAML file is valid.") + return 0