# Buggy code
def build(path=None, image=None, cache=True, rm=True, api_response=False, fileobj=None):
    """
    Builds a docker image from a Dockerfile or a URL

    path
        Path to directory on the Minion containing a Dockerfile

    image
        Image to be built, in ``repo:tag`` notation. If just the repository
        name is passed, a tag name of ``latest`` will be assumed. If building
        from a URL, this parameted can be omitted.

    cache : True
        Set to ``False`` to force the build process not to use the Docker image
        cache, and pull all required intermediate image layers

    rm : True
        Remove intermediate containers created during build

    api_response : False
        If ``True``: an ``API_Response`` key will be present in the return
        data, containing the raw output from the Docker API.

    fileobj
        Allows for a file-like object containing the contents of the Dockerfile
        to be passed in place of a file ``path`` argument. This argument should
        not be used from the CLI, only from other Salt code.


    **RETURN DATA**

    A dictionary containing one or more of the following keys:

    - ``Id`` - ID of the newly-built image
    - ``Time_Elapsed`` - Time in seconds taken to perform the build
    - ``Intermediate_Containers`` - IDs of containers created during the course
      of the build process

      *(Only present if rm=False)*
    - ``Images`` - A dictionary containing one or more of the following keys:
        - ``Already_Pulled`` - Layers that that were already present on the
          Minion
        - ``Pulled`` - Layers that that were pulled

      *(Only present if the image specified by the "image" argument was not
      present on the Minion, or if cache=False)*
    - ``Status`` - A string containing a summary of the pull action (usually a
      message saying that an image was downloaded, or that it was up to date).

      *(Only present if the image specified by the "image" argument was not
      present on the Minion, or if cache=False)*


    CLI Example:

    .. code-block:: bash

        salt myminion dockerng.build /path/to/docker/build/dir image=myimage:dev
        salt myminion dockerng.build https://github.com/myuser/myrepo.git image=myimage:latest
    """
    _prep_pull()

    image = ":".join(_get_repo_tag(image))
    time_started = time.time()
    response = _client_wrapper(
        "build",
        path=path,
        tag=image,
        quiet=False,
        fileobj=fileobj,
        rm=rm,
        nocache=not cache,
    )
    ret = {"Time_Elapsed": time.time() - time_started}
    _clear_context()

    if not response:
        raise CommandExecutionError(
            "Build failed for {0}, no response returned from Docker API".format(image)
        )

    stream_data = [json.loads(x) for x in response]
    errors = []
    # Iterate through API response and collect information
    for item in stream_data:
        try:
            item_type = next(iter(item))
        except StopIteration:
            continue
        if item_type == "status":
            _pull_status(ret, item)
        if item_type == "stream":
            _build_status(ret, item)
        elif item_type == "errorDetail":
            _error_detail(errors, item)

    if "Id" not in ret:
        # API returned information, but there was no confirmation of a
        # successful build.
        msg = "Build failed for {0}".format(image)
        log.error(msg)
        log.error(stream_data)
        if errors:
            msg += ". Error(s) follow:\n\n{0}".format("\n\n".join(errors))
        raise CommandExecutionError(msg)

    for image_id, image_info in six.iteritems(images()):
        if image_id.startswith(ret["Id"]):
            if image in image_info.get("RepoTags", []):
                ret["Image"] = image
            else:
                ret["Warning"] = "Failed to tag image as {0}".format(image)

    if api_response:
        ret["API_Response"] = stream_data

    if rm:
        ret.pop("Intermediate_Containers", None)
    return ret


# Traceback (ValueError)
bash-3.2# salt-call --local dockerng.build /Users/mzzhang/powerdns_docker image=myimage:dev
[DEBUG   ] Configuration file path: /etc/salt/minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Please install 'virt-what' to improve results of the 'virtual' grain.
[WARNING ] /opt/salt/lib/python2.7/site-packages/salt/grains/core.py:1493: DeprecationWarning: The "osmajorrelease" will be a type of an integer.

[DEBUG   ] Determining pillar cache
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded config.get
[DEBUG   ] Trying paths: ['/Users/mzzhang/.docker/config.json', '/Users/mzzhang/.dockercfg']
[DEBUG   ] No config file found
[DEBUG   ] "GET /version HTTP/1.1" 200 193
[DEBUG   ] "GET /v1.24/version HTTP/1.1" 200 193
[DEBUG   ] LazyLoaded dockerng.build
[DEBUG   ] "GET /v1.24/images/json?only_ids=0&amp;all=1 HTTP/1.1" 200 583
[DEBUG   ] Looking for auth config
[DEBUG   ] No auth config in memory - loading from filesystem
[DEBUG   ] Trying paths: ['/Users/mzzhang/.docker/config.json', '/Users/mzzhang/.dockercfg']
[DEBUG   ] No config file found
[DEBUG   ] No auth config found
[DEBUG   ] "POST /v1.24/build?q=False&amp;pull=False&amp;t=myimage%3Adev&amp;nocache=False&amp;forcerm=False&amp;rm=True HTTP/1.1" 200 None
########################################################################
################this is the print I added#######################################
response starts
{u'stream': u'Step 1 : FROM ubuntu:latest\n'} ############ print json.loads(x) in dockerng.py
{"stream":" ---\u003e f753707788c5\n"} ############## print s in decoder.py
{"stream":"Step 2 : ADD test.sh /usr/local/bin/test.sh\n"}####

40   ################## end
100  ################## len(s)
########################################################################
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
ValueError: Extra data: line 2 column 1 - line 3 column 1 (char 40 - 100)
Traceback (most recent call last):
File "/opt/salt/bin/salt-call", line 11, in <module>
salt_call()
File "/opt/salt/lib/python2.7/site-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/opt/salt/lib/python2.7/site-packages/salt/modules/dockerng.py", line 3463, in build
print json.loads(x)
File "/opt/salt/lib/python2.7/json/__init__.py", line 339, in loads
return _default_decoder.decode(s)
File "/opt/salt/lib/python2.7/json/decoder.py", line 370, in decode
raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1 - line 3 column 1 (char 40 - 100)
Traceback (most recent call last):
File "/opt/salt/bin/salt-call", line 11, in <module>
salt_call()
File "/opt/salt/lib/python2.7/site-packages/salt/scripts.py", line 352, in salt_call
client.run()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/opt/salt/lib/python2.7/site-packages/salt/cli/caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "/opt/salt/lib/python2.7/site-packages/salt/modules/dockerng.py", line 3463, in build
print json.loads(x)
File "/opt/salt/lib/python2.7/json/__init__.py", line 339, in loads
return _default_decoder.decode(s)
File "/opt/salt/lib/python2.7/json/decoder.py", line 370, in decode
raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1 - line 3 column 1 (char 40 - 100)

# Fixed code
def build(path=None, image=None, cache=True, rm=True, api_response=False, fileobj=None):
    """
    Builds a docker image from a Dockerfile or a URL

    path
        Path to directory on the Minion containing a Dockerfile

    image
        Image to be built, in ``repo:tag`` notation. If just the repository
        name is passed, a tag name of ``latest`` will be assumed. If building
        from a URL, this parameted can be omitted.

    cache : True
        Set to ``False`` to force the build process not to use the Docker image
        cache, and pull all required intermediate image layers

    rm : True
        Remove intermediate containers created during build

    api_response : False
        If ``True``: an ``API_Response`` key will be present in the return
        data, containing the raw output from the Docker API.

    fileobj
        Allows for a file-like object containing the contents of the Dockerfile
        to be passed in place of a file ``path`` argument. This argument should
        not be used from the CLI, only from other Salt code.


    **RETURN DATA**

    A dictionary containing one or more of the following keys:

    - ``Id`` - ID of the newly-built image
    - ``Time_Elapsed`` - Time in seconds taken to perform the build
    - ``Intermediate_Containers`` - IDs of containers created during the course
      of the build process

      *(Only present if rm=False)*
    - ``Images`` - A dictionary containing one or more of the following keys:
        - ``Already_Pulled`` - Layers that that were already present on the
          Minion
        - ``Pulled`` - Layers that that were pulled

      *(Only present if the image specified by the "image" argument was not
      present on the Minion, or if cache=False)*
    - ``Status`` - A string containing a summary of the pull action (usually a
      message saying that an image was downloaded, or that it was up to date).

      *(Only present if the image specified by the "image" argument was not
      present on the Minion, or if cache=False)*


    CLI Example:

    .. code-block:: bash

        salt myminion dockerng.build /path/to/docker/build/dir image=myimage:dev
        salt myminion dockerng.build https://github.com/myuser/myrepo.git image=myimage:latest
    """
    _prep_pull()

    image = ":".join(_get_repo_tag(image))
    time_started = time.time()
    response = _client_wrapper(
        "build",
        path=path,
        tag=image,
        quiet=False,
        fileobj=fileobj,
        rm=rm,
        nocache=not cache,
    )
    ret = {"Time_Elapsed": time.time() - time_started}
    _clear_context()

    if not response:
        raise CommandExecutionError(
            "Build failed for {0}, no response returned from Docker API".format(image)
        )

    stream_data = []
    for line in response:
        stream_data.extend(json.loads(line, cls=DockerJSONDecoder))
    errors = []
    # Iterate through API response and collect information
    for item in stream_data:
        try:
            item_type = next(iter(item))
        except StopIteration:
            continue
        if item_type == "status":
            _pull_status(ret, item)
        if item_type == "stream":
            _build_status(ret, item)
        elif item_type == "errorDetail":
            _error_detail(errors, item)

    if "Id" not in ret:
        # API returned information, but there was no confirmation of a
        # successful build.
        msg = "Build failed for {0}".format(image)
        log.error(msg)
        log.error(stream_data)
        if errors:
            msg += ". Error(s) follow:\n\n{0}".format("\n\n".join(errors))
        raise CommandExecutionError(msg)

    for image_id, image_info in six.iteritems(images()):
        if image_id.startswith(ret["Id"]):
            if image in image_info.get("RepoTags", []):
                ret["Image"] = image
            else:
                ret["Warning"] = "Failed to tag image as {0}".format(image)

    if api_response:
        ret["API_Response"] = stream_data

    if rm:
        ret.pop("Intermediate_Containers", None)
    return ret