github.com/rentongzhang/docker@v1.8.2-rc1/api/client/inspect.go (about)

     1  package client
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"strings"
     9  	"text/template"
    10  
    11  	"github.com/docker/docker/api/types"
    12  	Cli "github.com/docker/docker/cli"
    13  	flag "github.com/docker/docker/pkg/mflag"
    14  )
    15  
    16  var funcMap = template.FuncMap{
    17  	"json": func(v interface{}) string {
    18  		a, _ := json.Marshal(v)
    19  		return string(a)
    20  	},
    21  }
    22  
    23  // CmdInspect displays low-level information on one or more containers or images.
    24  //
    25  // Usage: docker inspect [OPTIONS] CONTAINER|IMAGE [CONTAINER|IMAGE...]
    26  func (cli *DockerCli) CmdInspect(args ...string) error {
    27  	cmd := Cli.Subcmd("inspect", []string{"CONTAINER|IMAGE [CONTAINER|IMAGE...]"}, "Return low-level information on a container or image", true)
    28  	tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template")
    29  	inspectType := cmd.String([]string{"-type"}, "", "Return JSON for specified type, (e.g image or container)")
    30  	cmd.Require(flag.Min, 1)
    31  
    32  	cmd.ParseFlags(args, true)
    33  
    34  	var tmpl *template.Template
    35  	var err error
    36  	var obj []byte
    37  
    38  	if *tmplStr != "" {
    39  		if tmpl, err = template.New("").Funcs(funcMap).Parse(*tmplStr); err != nil {
    40  			return Cli.StatusError{StatusCode: 64,
    41  				Status: "Template parsing error: " + err.Error()}
    42  		}
    43  	}
    44  
    45  	if *inspectType != "" && *inspectType != "container" && *inspectType != "image" {
    46  		return fmt.Errorf("%q is not a valid value for --type", *inspectType)
    47  	}
    48  
    49  	indented := new(bytes.Buffer)
    50  	indented.WriteString("[\n")
    51  	status := 0
    52  	isImage := false
    53  
    54  	for _, name := range cmd.Args() {
    55  
    56  		if *inspectType == "" || *inspectType == "container" {
    57  			obj, _, err = readBody(cli.call("GET", "/containers/"+name+"/json", nil, nil))
    58  			if err != nil && *inspectType == "container" {
    59  				if strings.Contains(err.Error(), "No such") {
    60  					fmt.Fprintf(cli.err, "Error: No such container: %s\n", name)
    61  				} else {
    62  					fmt.Fprintf(cli.err, "%s", err)
    63  				}
    64  				status = 1
    65  				continue
    66  			}
    67  		}
    68  
    69  		if obj == nil && (*inspectType == "" || *inspectType == "image") {
    70  			obj, _, err = readBody(cli.call("GET", "/images/"+name+"/json", nil, nil))
    71  			isImage = true
    72  			if err != nil {
    73  				if strings.Contains(err.Error(), "No such") {
    74  					if *inspectType == "" {
    75  						fmt.Fprintf(cli.err, "Error: No such image or container: %s\n", name)
    76  					} else {
    77  						fmt.Fprintf(cli.err, "Error: No such image: %s\n", name)
    78  					}
    79  				} else {
    80  					fmt.Fprintf(cli.err, "%s", err)
    81  				}
    82  				status = 1
    83  				continue
    84  			}
    85  
    86  		}
    87  
    88  		if tmpl == nil {
    89  			if err := json.Indent(indented, obj, "", "    "); err != nil {
    90  				fmt.Fprintf(cli.err, "%s\n", err)
    91  				status = 1
    92  				continue
    93  			}
    94  		} else {
    95  			rdr := bytes.NewReader(obj)
    96  			dec := json.NewDecoder(rdr)
    97  
    98  			if isImage {
    99  				inspPtr := types.ImageInspect{}
   100  				if err := dec.Decode(&inspPtr); err != nil {
   101  					fmt.Fprintf(cli.err, "%s\n", err)
   102  					status = 1
   103  					continue
   104  				}
   105  				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
   106  					rdr.Seek(0, 0)
   107  					var raw interface{}
   108  					if err := dec.Decode(&raw); err != nil {
   109  						return err
   110  					}
   111  					if err = tmpl.Execute(cli.out, raw); err != nil {
   112  						return err
   113  					}
   114  				}
   115  			} else {
   116  				inspPtr := types.ContainerJSON{}
   117  				if err := dec.Decode(&inspPtr); err != nil {
   118  					fmt.Fprintf(cli.err, "%s\n", err)
   119  					status = 1
   120  					continue
   121  				}
   122  				if err := tmpl.Execute(cli.out, inspPtr); err != nil {
   123  					rdr.Seek(0, 0)
   124  					var raw interface{}
   125  					if err := dec.Decode(&raw); err != nil {
   126  						return err
   127  					}
   128  					if err = tmpl.Execute(cli.out, raw); err != nil {
   129  						return err
   130  					}
   131  				}
   132  			}
   133  			cli.out.Write([]byte{'\n'})
   134  		}
   135  		indented.WriteString(",")
   136  	}
   137  
   138  	if indented.Len() > 1 {
   139  		// Remove trailing ','
   140  		indented.Truncate(indented.Len() - 1)
   141  	}
   142  	indented.WriteString("]\n")
   143  
   144  	if tmpl == nil {
   145  		// Note that we will always write "[]" when "-f" isn't specified,
   146  		// to make sure the output would always be array, see
   147  		// https://github.com/docker/docker/pull/9500#issuecomment-65846734
   148  		if _, err := io.Copy(cli.out, indented); err != nil {
   149  			return err
   150  		}
   151  	}
   152  
   153  	if status != 0 {
   154  		return Cli.StatusError{StatusCode: status}
   155  	}
   156  	return nil
   157  }