Blame SOURCES/bz1500012-01-provide-a-hint-about-the-set-opti.patch

d01bb5
From c85f907253f6379ad726a7f54635ccbe0b64af4c Mon Sep 17 00:00:00 2001
d01bb5
From: Ivan Devat <idevat@redhat.com>
d01bb5
Date: Mon, 4 Nov 2019 14:52:03 +0100
d01bb5
Subject: [PATCH 1/4] squash bz1500012 provide a hint about the set opti
d01bb5
d01bb5
d2754533 doc: fix `pcs constraint colocation add` command
d01bb5
abb8f0ea don't allow empty value for constraint options
d01bb5
---
d01bb5
 pcs/cli/common/parse_args.py | 9 +++++++--
d01bb5
 pcs/constraint.py            | 7 +++++--
d01bb5
 pcs/pcs.8                    | 4 ++--
d01bb5
 pcs/test/test_constraints.py | 9 +++++++++
d01bb5
 pcs/usage.py                 | 6 +++---
d01bb5
 5 files changed, 26 insertions(+), 9 deletions(-)
d01bb5
d01bb5
diff --git a/pcs/cli/common/parse_args.py b/pcs/cli/common/parse_args.py
d01bb5
index 6a3210ac..23d8799d 100644
d01bb5
--- a/pcs/cli/common/parse_args.py
d01bb5
+++ b/pcs/cli/common/parse_args.py
d01bb5
@@ -46,7 +46,7 @@ def split_list(arg_list, separator):
d01bb5
     bounds = zip([0]+[i+1 for i in separator_indexes], separator_indexes+[None])
d01bb5
     return [arg_list[i:j] for i, j in bounds]
d01bb5
 
d01bb5
-def split_option(arg):
d01bb5
+def split_option(arg, allow_empty_value=True):
d01bb5
     """
d01bb5
     Get (key, value) from a key=value commandline argument.
d01bb5
 
d01bb5
@@ -54,12 +54,17 @@ def split_option(arg):
d01bb5
     CmdLineInputError if the argument cannot be splitted.
d01bb5
 
d01bb5
     string arg -- commandline argument
d01bb5
+    allow_empty_value -- if True, empty value is allowed. Otherwise,
d01bb5
+        CmdLineInputError exception is raised
d01bb5
     """
d01bb5
     if "=" not in arg:
d01bb5
         raise CmdLineInputError("missing value of '{0}' option".format(arg))
d01bb5
     if arg.startswith("="):
d01bb5
         raise CmdLineInputError("missing key in '{0}' option".format(arg))
d01bb5
-    return arg.split("=", 1)
d01bb5
+    key, value = arg.split("=", 1)
d01bb5
+    if not (value or allow_empty_value):
d01bb5
+        raise CmdLineInputError("value of '{0}' option is empty".format(key))
d01bb5
+    return key, value
d01bb5
 
d01bb5
 def prepare_options(cmdline_args):
d01bb5
     """return dictionary of options from commandline key=value args"""
d01bb5
diff --git a/pcs/constraint.py b/pcs/constraint.py
d01bb5
index c9f6fd5f..ca12aaa7 100644
d01bb5
--- a/pcs/constraint.py
d01bb5
+++ b/pcs/constraint.py
d01bb5
@@ -208,7 +208,10 @@ def colocation_add(argv):
d01bb5
             return SCORE_INFINITY, []
d01bb5
         score = SCORE_INFINITY if "=" in argv[0] else argv.pop(0)
d01bb5
         # create a list of 2-tuples (name, value)
d01bb5
-        arg_array = [parse_args.split_option(arg) for arg in argv]
d01bb5
+        arg_array = [
d01bb5
+            parse_args.split_option(arg, allow_empty_value=False)
d01bb5
+            for arg in argv
d01bb5
+        ]
d01bb5
         return score, arg_array
d01bb5
 
d01bb5
     def _validate_and_prepare_role(role):
d01bb5
@@ -444,7 +447,7 @@ def _order_add(resource1, resource2, options_list):
d01bb5
         elif arg == "nonsymmetrical":
d01bb5
             sym = "false"
d01bb5
         else:
d01bb5
-            name, value = parse_args.split_option(arg)
d01bb5
+            name, value = parse_args.split_option(arg, allow_empty_value=False)
d01bb5
             if name == "id":
d01bb5
                 id_valid, id_error = utils.validate_xml_id(
d01bb5
                     value, "constraint id"
d01bb5
diff --git a/pcs/pcs.8 b/pcs/pcs.8
d01bb5
index 5670f458..f08b5e46 100644
d01bb5
--- a/pcs/pcs.8
d01bb5
+++ b/pcs/pcs.8
d01bb5
@@ -562,8 +562,8 @@ Remove resource from any ordering constraint
d01bb5
 colocation [show] [\fB\-\-full\fR]
d01bb5
 List all current colocation constraints (if \fB\-\-full\fR is specified show the internal constraint id's as well).
d01bb5
 .TP
d01bb5
-colocation add [master|slave] <source resource id> with [master|slave] <target resource id> [score] [options] [id=constraint\-id]
d01bb5
-Request <source resource> to run on the same node where pacemaker has determined <target resource> should run.  Positive values of score mean the resources should be run on the same node, negative values mean the resources should not be run on the same node.  Specifying 'INFINITY' (or '\-INFINITY') for the score forces <source resource> to run (or not run) with <target resource> (score defaults to "INFINITY").  A role can be master or slave (if no role is specified, it defaults to 'started').
d01bb5
+colocation add [<role>] <source resource id> with [<role>] <target resource id> [score] [options] [id=constraint\-id]
d01bb5
+Request <source resource> to run on the same node where pacemaker has determined <target resource> should run.  Positive values of score mean the resources should be run on the same node, negative values mean the resources should not be run on the same node.  Specifying 'INFINITY' (or '\-INFINITY') for the score forces <source resource> to run (or not run) with <target resource> (score defaults to "INFINITY"). A role can be: 'Master', 'Slave', 'Started', 'Stopped' (if no role is specified, it defaults to 'Started').
d01bb5
 .TP
d01bb5
 colocation set <resource1> [resourceN]... [options] [set <resourceX> ... [options]] [setoptions [constraint_options]]
d01bb5
 Create a colocation constraint with a resource set. Available options are sequential=true/false and role=Stopped/Started/Master/Slave. Available constraint_options are id and either of: score, score\-attribute, score\-attribute\-mangle.
d01bb5
diff --git a/pcs/test/test_constraints.py b/pcs/test/test_constraints.py
d01bb5
index 36bcb652..3feaa053 100644
d01bb5
--- a/pcs/test/test_constraints.py
d01bb5
+++ b/pcs/test/test_constraints.py
d01bb5
@@ -262,6 +262,11 @@ Ticket Constraints:
d01bb5
         ac(o,"Location Constraints:\nOrdering Constraints:\n  stop D1 then stop D2 (kind:Mandatory) (id:order-D1-D2-mandatory)\n  start D1 then start D2 (kind:Mandatory) (id:order-D1-D2-mandatory-1)\nColocation Constraints:\nTicket Constraints:\n")
d01bb5
         assert r == 0
d01bb5
 
d01bb5
+    def test_order_options_empty_value(self):
d01bb5
+        o, r = pcs("constraint order D1 then D2 option1=")
d01bb5
+        self.assertIn("value of 'option1' option is empty", o)
d01bb5
+        self.assertEqual(r, 1)
d01bb5
+
d01bb5
     def test_order_too_many_resources(self):
d01bb5
         msg = (
d01bb5
             "Error: Multiple 'then's cannot be specified.\n"
d01bb5
@@ -525,6 +530,10 @@ Ticket Constraints:
d01bb5
         self.assertIn(msg, o)
d01bb5
         self.assertEqual(r, 1)
d01bb5
 
d01bb5
+    def test_colocation_options_empty_value(self):
d01bb5
+        o, r = pcs("constraint colocation add D1 with D2 option1=")
d01bb5
+        self.assertIn("value of 'option1' option is empty", o)
d01bb5
+        self.assertEqual(r, 1)
d01bb5
 
d01bb5
     def testColocationSets(self):
d01bb5
         # see also BundleColocation
d01bb5
diff --git a/pcs/usage.py b/pcs/usage.py
d01bb5
index 18baaf0e..37c92d26 100644
d01bb5
--- a/pcs/usage.py
d01bb5
+++ b/pcs/usage.py
d01bb5
@@ -1200,7 +1200,7 @@ Commands:
d01bb5
         List all current colocation constraints (if --full is specified show
d01bb5
         the internal constraint id's as well).
d01bb5
 
d01bb5
-    colocation add [master|slave] <source resource id> with [master|slave]
d01bb5
+    colocation add [<role>] <source resource id> with [<role>]
d01bb5
                    <target resource id> [score] [options] [id=constraint-id]
d01bb5
         Request <source resource> to run on the same node where pacemaker has
d01bb5
         determined <target resource> should run.  Positive values of score
d01bb5
@@ -1208,8 +1208,8 @@ Commands:
d01bb5
         mean the resources should not be run on the same node.  Specifying
d01bb5
         'INFINITY' (or '-INFINITY') for the score forces <source resource> to
d01bb5
         run (or not run) with <target resource> (score defaults to "INFINITY").
d01bb5
-        A role can be master or slave (if no role is specified, it defaults to
d01bb5
-        'started').
d01bb5
+        A role can be: 'Master', 'Slave', 'Started', 'Stopped' (if no role is
d01bb5
+        specified, it defaults to 'Started').
d01bb5
 
d01bb5
     colocation set <resource1> [resourceN]... [options]
d01bb5
                [set <resourceX> ... [options]]
d01bb5
-- 
d01bb5
2.21.0
d01bb5