# Buggy code
def _sdc_mdata(mdata_list=None, mdata_get=None):
    """
    SDC Metadata specified by there specs
    https://eng.joyent.com/mdata/datadict.html
    """
    grains = {}
    sdc_text_keys = [
        "uuid",
        "server_uuid",
        "datacenter_name",
        "hostname",
        "dns_domain",
    ]
    sdc_json_keys = [
        "resolvers",
        "nics",
        "routes",
    ]

    if not mdata_list:
        mdata_list = salt.utils.path.which("mdata-list")

    if not mdata_get:
        mdata_get = salt.utils.path.which("mdata-get")

    if not mdata_list or not mdata_get:
        return grains

    for mdata_grain in sdc_text_keys + sdc_json_keys:
        mdata_value = __salt__["cmd.run"](
            "{0} sdc:{1}".format(mdata_get, mdata_grain), ignore_retcode=True
        )

        if not mdata_value.startswith("No metadata for "):
            if "mdata" not in grains:
                grains["mdata"] = {}
            if "sdc" not in grains["mdata"]:
                grains["mdata"]["sdc"] = {}

            log.debug(
                "found mdata entry sdc:%s with value %s", mdata_grain, mdata_value
            )
            mdata_grain = mdata_grain.replace("-", "_")
            mdata_grain = mdata_grain.replace(":", "_")
            if mdata_grain in sdc_json_keys:
                grains["mdata"]["sdc"][mdata_grain] = salt.utils.json.loads(mdata_value)
            else:
                grains["mdata"]["sdc"][mdata_grain] = mdata_value

    return grains


# Traceback (ValueError)
# salt-call grains.items
[WARNING ] /opt/tools/lib/python3.7/site-packages/salt/loader.py:772: DeprecationWarning: dist() and linux_distribution() functions are deprecated in Python 3.5
ret = funcs[key]()

[WARNING ] /opt/tools/lib/python3.7/site-packages/salt/utils/path.py:265: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working
if not isinstance(exes, collections.Iterable):

[CRITICAL] Failed to load grains defined in grain file mdata.mdata in function <function mdata at 0x3a658f8>, error:
Traceback (most recent call last):
File "/opt/tools/lib/python3.7/site-packages/salt/loader.py", line 798, in grains
ret = funcs[key](**kwargs)
File "/opt/tools/lib/python3.7/site-packages/salt/grains/mdata.py", line 160, in mdata
grains = salt.utils.dictupdate.update(grains, _user_mdata(mdata_list, mdata_get), merge_lists=True)
File "/opt/tools/lib/python3.7/site-packages/salt/grains/mdata.py", line 66, in _user_mdata
mdata_value = __salt__['cmd.run']('{0} {1}'.format(mdata_get, mdata_grain), ignore_retcode=True)
File "/opt/tools/lib/python3.7/site-packages/salt/modules/cmdmod.py", line 1167, in run
**kwargs)
File "/opt/tools/lib/python3.7/site-packages/salt/modules/cmdmod.py", line 633, in _run
cmd = salt.utils.args.shlex_split(cmd)
File "/opt/tools/lib/python3.7/site-packages/salt/utils/args.py", line 295, in shlex_split
shlex.split(salt.utils.stringutils.to_str(s), **kwargs)
File "/opt/tools/lib/python3.7/shlex.py", line 305, in split
return list(lex)
File "/opt/tools/lib/python3.7/shlex.py", line 295, in __next__
token = self.get_token()
File "/opt/tools/lib/python3.7/shlex.py", line 105, in get_token
raw = self.read_token()
File "/opt/tools/lib/python3.7/shlex.py", line 187, in read_token
raise ValueError("No closing quotation")
ValueError: No closing quotation
local:
----------
cpu_flags:
- fsgsbase
- avx2
- fma
- bmi2
- bmi1
- rdrand
- f16c
- vmx
- avx
- xsave
- pclmulqdq
- aes
- movbe
- sse4.2
- sse4.1
- ssse3
- amd_lzcnt
- popcnt
- tscp
- cx16
- sse3
- sse2
- sse
- fxsr
- mmx
- cmov
- amd_sysc
- cx8
- tsc
- fpu
cpu_model:
Intel(r) Xeon(r) CPU E5-2670 v3 @ 2.30GHz
cpuarch:
amd64
gid:
0
gpus:
groupname:
root
host:
smartos2
hwaddr_interfaces:
----------
e1000g0:
00:50:56:b7:b9:58
zone_net0:
02:08:20:41:2a:70
imageversion:
Unknown
kernel:
SunOS
kernelrelease:
5.11
kernelversion:
joyent_20190703T233036Z
locale_info:
----------
defaultencoding:
UTF-8
defaultlanguage:
el_GR
detectedencoding:
UTF-8

master:
salt
mem_total:
16383
num_cpus:
4
num_gpus:
0
os:
SmartOS
os_family:
Solaris
osarch:
amd64
osfinger:
SmartOS-2019
osfullname:
SmartOS
osmajorrelease:
2019
osrelease:
2019.07.03
osrelease_info:
- 2019
- 7
- 3
osrelease_stamp:
20190703T233036Z
path:
/opt/tools/sbin:/opt/tools/bin:/usr/bin:/usr/sbin:/smartdc/bin:/opt/smartdc/bin:/opt/local/bin:/opt/local/sbin:/opt/tools/bin:/opt/tools/sbin:/opt/smartdc/agents/bin
pid:
15009
pkgin_repositories:
pkgsrcpath:
Unknown
pkgsrcversion:
Unknown
ps:
/usr/ucb/ps auxwww
pythonexecutable:
/opt/tools/bin/python3.7
pythonpath:
- /opt/tools/bin
- /opt/tools/lib/python37.zip
- /opt/tools/lib/python3.7
- /opt/tools/lib/python3.7/lib-dynload
- /opt/tools/lib/python3.7/site-packages
pythonversion:
- 3
- 7
- 3
- final
- 0
saltpath:
/opt/tools/lib/python3.7/site-packages/salt
saltversion:
2019.2.0
saltversioninfo:
- 2019
- 2
- 0
- 0
shell:
/usr/bin/bash
swap_total:
30297
uid:
0
username:
root
virtual:
VMware
zfs_feature_flags:
True
zfs_support:
True
zmqversion:
4.3.1
zoneid:
0
1
zonename:
global
zpool:
----------
zones:
154618822656

# Fixed code
def _sdc_mdata(mdata_list=None, mdata_get=None):
    """
    SDC Metadata specified by there specs
    https://eng.joyent.com/mdata/datadict.html
    """
    grains = {}
    sdc_text_keys = [
        "uuid",
        "server_uuid",
        "datacenter_name",
        "hostname",
        "dns_domain",
        "alias",
    ]
    sdc_json_keys = [
        "resolvers",
        "nics",
        "routes",
    ]

    if not mdata_list:
        mdata_list = salt.utils.path.which("mdata-list")

    if not mdata_get:
        mdata_get = salt.utils.path.which("mdata-get")

    if not mdata_list or not mdata_get:
        return grains

    for mdata_grain in sdc_text_keys + sdc_json_keys:
        mdata_value = __salt__["cmd.run"](
            "{0} sdc:{1}".format(mdata_get, mdata_grain), ignore_retcode=True
        )
        if mdata_value.startswith("ERROR:"):
            log.warning(
                "unable to read sdc:{0} via mdata-get, mdata grain may be incomplete.".format(
                    mdata_grain,
                )
            )
            continue

        if not mdata_value.startswith("No metadata for "):
            if "mdata" not in grains:
                grains["mdata"] = {}
            if "sdc" not in grains["mdata"]:
                grains["mdata"]["sdc"] = {}

            log.debug(
                "found mdata entry sdc:%s with value %s", mdata_grain, mdata_value
            )
            mdata_grain = mdata_grain.replace("-", "_")
            mdata_grain = mdata_grain.replace(":", "_")
            if mdata_grain in sdc_json_keys:
                grains["mdata"]["sdc"][mdata_grain] = salt.utils.json.loads(mdata_value)
            else:
                grains["mdata"]["sdc"][mdata_grain] = mdata_value

    return grains