diff --git a/bash/patchman-client b/bash/patchman-client index 7b07bba..a1f257e 100755 --- a/bash/patchman-client +++ b/bash/patchman-client @@ -946,7 +946,7 @@ build_json_report() { # Convert tags to JSON array local tags_json="[]" if [ -n "${tags}" ] && [ "${tags}" != "Default" ] ; then - tags_json=$(echo "${tags}" | tr ',' '\n' | jq -R . | jq -s .) + tags_json=$(echo "${tags}" | jq -R 'if test(",") then split(",") else [splits("\\s+")] end | map(gsub("^\\s+|\\s+$"; "")) | map(select(length > 0))') fi # Convert reboot to boolean diff --git a/bash/patchman-client.conf b/bash/patchman-client.conf index 666dd54..483d9a3 100644 --- a/bash/patchman-client.conf +++ b/bash/patchman-client.conf @@ -4,7 +4,7 @@ server=https://patchman.example.com # Options to curl curl_options="--insecure --connect-timeout 60 --max-time 300" -# Space delimited tags to send +# Comma or space delimited tags to send tags="Server" # Does the client output a report of the upload (e.g. for cronjob output) diff --git a/debian/control b/debian/control index 4daf79b..009dba1 100644 --- a/debian/control +++ b/debian/control @@ -23,7 +23,7 @@ Description: Patchman client - meta-package with hooks Package: patchman-client-bash Architecture: all -Depends: ${misc:Depends}, bash, curl, coreutils, gawk, grep, sed +Depends: ${misc:Depends}, bash, curl, coreutils, gawk, grep, sed, jq Recommends: jq Provides: patchman-client-impl Description: Patchman client - bash implementation diff --git a/go/lib/report/report.go b/go/lib/report/report.go index ddddc87..9805934 100644 --- a/go/lib/report/report.go +++ b/go/lib/report/report.go @@ -104,14 +104,16 @@ func NewReport(osInfo si.OSInfo) *Report { } } -// SetTags sets the tags from a comma-separated string +// SetTags sets the tags from a comma or space delimited string func (r *Report) SetTags(tags string) { - if tags == "" { - return + parts := strings.Fields(tags) + if strings.Contains(tags, ",") { + parts = strings.Split(tags, ",") } - r.Tags = strings.Split(tags, ",") - for i, tag := range r.Tags { - r.Tags[i] = strings.TrimSpace(tag) + for _, tag := range parts { + if tag = strings.TrimSpace(tag); tag != "" { + r.Tags = append(r.Tags, tag) + } } } diff --git a/go/lib/report/report_test.go b/go/lib/report/report_test.go index 70c2362..987d882 100644 --- a/go/lib/report/report_test.go +++ b/go/lib/report/report_test.go @@ -52,6 +52,22 @@ func TestSetTags(t *testing.T) { } } +func TestSetTagsDelimiters(t *testing.T) { + cases := map[string][]string{ + "web prod": {"web", "prod"}, + "web, prod": {"web", "prod"}, + "web,,prod,": {"web", "prod"}, + " ": nil, + } + for in, want := range cases { + rpt := NewReport(si.OSInfo{Hostname: "test"}) + rpt.SetTags(in) + if strings.Join(rpt.Tags, "|") != strings.Join(want, "|") { + t.Errorf("SetTags(%q) = %q, want %q", in, rpt.Tags, want) + } + } +} + func TestAddRPMs(t *testing.T) { osInfo := si.OSInfo{Hostname: "test"} rpt := NewReport(osInfo) diff --git a/patchman-client.spec b/patchman-client.spec index 1f903b1..27c0441 100644 --- a/patchman-client.spec +++ b/patchman-client.spec @@ -19,7 +19,7 @@ the client implementations (bash, python, or go). %package bash Summary: Patchman client - bash implementation -Requires: bash curl coreutils gawk grep sed +Requires: bash curl coreutils gawk grep sed jq Recommends: jq Provides: patchman-client-impl diff --git a/python/patchman_client/client.py b/python/patchman_client/client.py index cf3911a..52b8258 100755 --- a/python/patchman_client/client.py +++ b/python/patchman_client/client.py @@ -67,7 +67,8 @@ def __init__( self.server = server.rstrip('/') if server else '' self.api_key = api_key self.hostname = hostname or self._get_hostname() - self.tags = [t.strip() for t in tags.split(',') if t.strip()] if tags else [] + sep = ',' if ',' in tags else None + self.tags = [t.strip() for t in tags.split(sep) if t.strip()] if tags else [] self.verbose = verbose self.debug = debug self.local_updates = local_updates diff --git a/tests/test_client_output.py b/tests/test_client_output.py index 644f824..2eafdeb 100644 --- a/tests/test_client_output.py +++ b/tests/test_client_output.py @@ -1654,6 +1654,26 @@ def test_config_quoted_values(self): finally: os.unlink(conf_path) + def test_tags_comma_or_space_delimited(self): + """Tags split on commas if present, otherwise on whitespace.""" + import importlib + spec = importlib.util.spec_from_file_location( + 'client', os.path.join( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))), + 'python', 'patchman_client', 'client.py', + ), + ) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + for tags, expected in ( + ('web prod', ['web', 'prod']), + ('web, prod', ['web', 'prod']), + ('my tag,web', ['my tag', 'web']), + ('', []), + ): + client = mod.PatchmanClient(hostname='test', tags=tags) + self.assertEqual(client.tags, expected) + if __name__ == '__main__': unittest.main()