From fe61ae2161132bf2b5afd7e877f305440606220c Mon Sep 17 00:00:00 2001 From: Ben Agricola Date: Tue, 1 May 2018 17:07:17 +0100 Subject: [PATCH] Add snabb config test functionality. Reworks `snabb config` command line parsing somewhat to allow `snabb config test` to work. `snabb config test` loads a schema passed with `-s` either by name (if already known by snabb) or by file path, then validates a passed configuration FILE against the schema. Signed-off-by: Ben Agricola --- src/lib/yang/yang.lua | 6 ++-- src/program/config/README | 1 + src/program/config/common.lua | 49 +++++++++++++++++++++--------- src/program/config/test/README | 18 +++++++++++ src/program/config/test/README.inc | 18 +++++++++++ src/program/config/test/test.lua | 12 ++++++++ 6 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 src/program/config/test/README create mode 100644 src/program/config/test/README.inc create mode 100644 src/program/config/test/test.lua diff --git a/src/lib/yang/yang.lua b/src/lib/yang/yang.lua index fac86acac3..6c0d38f86b 100644 --- a/src/lib/yang/yang.lua +++ b/src/lib/yang/yang.lua @@ -53,8 +53,10 @@ function load_configuration(filename, opts) end local function err(msg, ...) error(err_msg(msg, ...)) end local function log(msg, ...) - io.stderr:write(err_msg(msg, ...)..'\n') - io.stderr:flush() + if opts.verbose then + io.stderr:write(err_msg(msg, ...)..'\n') + io.stderr:flush() + end end local function assert(exp, msg, ...) if exp then return exp else err(msg, ...) end diff --git a/src/program/config/README b/src/program/config/README index 8f5a4ca6ee..4526dff3fc 100644 --- a/src/program/config/README +++ b/src/program/config/README @@ -4,6 +4,7 @@ Usage: snabb config get-state snabb config listen snabb config load + snabb config test snabb config remove snabb config set diff --git a/src/program/config/common.lua b/src/program/config/common.lua index b11f2d2e0f..208dc63ea1 100644 --- a/src/program/config/common.lua +++ b/src/program/config/common.lua @@ -73,6 +73,7 @@ function parse_command_line(args, opts) function handlers.s(arg) ret.schema_name = arg end function handlers.r(arg) ret.revision_date = arg end function handlers.c(arg) ret.socket = arg end + function handlers.v(arg) ret.verbose = true end function handlers.f(arg) assert(arg == "yang" or arg == "xpath", "Not valid output format") ret.format = arg @@ -80,30 +81,50 @@ function parse_command_line(args, opts) handlers['print-default'] = function () ret.print_default = true end - args = lib.dogetopt(args, handlers, "hs:r:c:f:", - {help="h", ['schema-name']="s", schema="s", + args = lib.dogetopt(args, handlers, "hvs:r:c:f:", + {help="h", verbose="v", ['schema-name']="s", schema="s", ['revision-date']="r", revision="r", socket="c", ['print-default']=0, format="f"}) + if #args == 0 then err() end - ret.instance_id = table.remove(args, 1) - local descr = call_leader(ret.instance_id, 'describe', {}) - if not ret.schema_name then - if opts.require_schema then err("missing --schema arg") end - ret.schema_name = descr.default_schema + + if opts.command == 'test' then + if #args > 1 then + ret.instance_id = table.remove(args, 1) + end + else + ret.instance_id = table.remove(args, 1) end - require('lib.yang.schema').set_default_capabilities(descr.capability) + + -- If instance ID was given, then load description from instance + if ret.instance_id then + local descr = call_leader(ret.instance_id, 'describe', {}) + -- If schema name was not explicitly passed, load from instance + if not ret.schema_name then + if opts.require_schema then err("missing --schema arg") end + ret.schema_name = descr.default_schema + end + require('lib.yang.schema').set_default_capabilities(descr.capability) + end + if not pcall(yang.load_schema_by_name, ret.schema_name) then - local response = call_leader( - ret.instance_id, 'get-schema', - {schema=ret.schema_name, revision=ret.revision_date}) - assert(not response.error, response.error) - yang.add_schema(response.source, ret.schema_name) + local schema_file = S.lstat(ret.schema_name) + if schema_file and schema_file.isreg then + ret.schema_name = yang.add_schema_file(ret.schema_name) + else + if not ret.instance_id then err("no schema loaded and instance id not given") end + local response = call_leader( + ret.instance_id, 'get-schema', + {schema=ret.schema_name, revision=ret.revision_date}) + assert(not response.error, response.error) + yang.add_schema(response.source, ret.schema_name) + end end if opts.with_config_file then if #args == 0 then err("missing config file argument") end local file = table.remove(args, 1) local opts = {schema_name=ret.schema_name, - revision_date=ret.revision_date} + revision_date=ret.revision_date, verbose=ret.verbose} ret.config_file = file ret.config = yang.load_configuration(file, opts) end diff --git a/src/program/config/test/README b/src/program/config/test/README new file mode 100644 index 0000000000..4d5554cd62 --- /dev/null +++ b/src/program/config/test/README @@ -0,0 +1,18 @@ +Usage: + snabb config test [OPTIONS] [ID] FILE + +Available options: + -s SCHEMA-NAME-OR-FILE-PATH + --schema SCHEMA-NAME-OR-FILE-PATH + --schema-name SCHEMA-NAME + + -r REVISION + --revision REVISION + --revision-date REVISION + + -v + --verbose + + -h + --help + diff --git a/src/program/config/test/README.inc b/src/program/config/test/README.inc new file mode 100644 index 0000000000..4d5554cd62 --- /dev/null +++ b/src/program/config/test/README.inc @@ -0,0 +1,18 @@ +Usage: + snabb config test [OPTIONS] [ID] FILE + +Available options: + -s SCHEMA-NAME-OR-FILE-PATH + --schema SCHEMA-NAME-OR-FILE-PATH + --schema-name SCHEMA-NAME + + -r REVISION + --revision REVISION + --revision-date REVISION + + -v + --verbose + + -h + --help + diff --git a/src/program/config/test/test.lua b/src/program/config/test/test.lua new file mode 100644 index 0000000000..ab32d1d7fd --- /dev/null +++ b/src/program/config/test/test.lua @@ -0,0 +1,12 @@ +-- Use of this source code is governed by the Apache 2.0 license; see COPYING. +module(..., package.seeall) + +local yang = require("lib.yang.yang") +local common = require("program.config.common") + +function run(args) + local opts = { command='test', with_config_file=true, is_config = false} + local ret, args = common.parse_command_line(args, opts) + + yang.print_config_for_schema_by_name(ret.schema_name, ret.config, io.stdout) +end