github.com/mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/metadata/diag.go (about) 1 /* 2 Copyright 2018 Mirantis 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package metadata 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "strings" 24 25 "github.com/ghodss/yaml" 26 27 "github.com/Mirantis/virtlet/pkg/diag" 28 "github.com/Mirantis/virtlet/pkg/metadata/types" 29 ) 30 31 const ( 32 indentStr = " " 33 ) 34 35 type metadataDumper struct { 36 store Store 37 out io.Writer 38 indent int 39 } 40 41 func newMetadataDumper(store Store, out io.Writer) *metadataDumper { 42 return &metadataDumper{store: store, out: out} 43 } 44 45 func (d *metadataDumper) withAddedIndent(toCall func()) { 46 d.indent++ 47 defer func() { 48 d.indent-- 49 }() 50 toCall() 51 } 52 53 func (d *metadataDumper) indentString() string { 54 return strings.Repeat(indentStr, d.indent) 55 } 56 57 func (d *metadataDumper) outputYaml(o interface{}) { 58 out, err := yaml.Marshal(o) 59 if err != nil { 60 fmt.Fprintf(d.out, "<error marshalling the object: %v", err) 61 } 62 indentStr := d.indentString() 63 for _, l := range strings.Split(string(out), "\n") { 64 if l != "" { 65 l = indentStr + l 66 } 67 fmt.Fprintln(d.out, l) 68 } 69 } 70 71 func (d *metadataDumper) output(format string, args ...interface{}) { 72 fmt.Fprintf(d.out, d.indentString()+format+"\n", args...) 73 } 74 75 func (d *metadataDumper) outputError(description string, err error) { 76 d.output("<error: %s: %v>", description, err) 77 } 78 79 func (d *metadataDumper) dump() { 80 d.output("Sandboxes:") 81 sandboxes, err := d.store.ListPodSandboxes(nil) 82 switch { 83 case err != nil: 84 d.outputError("can't list sandboxes", err) 85 case len(sandboxes) == 0: 86 d.output("no sandboxes found") 87 default: 88 d.withAddedIndent(func() { 89 for _, smeta := range sandboxes { 90 if sinfo, err := smeta.Retrieve(); err != nil { 91 d.outputError("can't retrieve sandbox", err) 92 } else if err := d.dumpSandbox(smeta.GetID(), sinfo); err != nil { 93 d.outputError("dumping sandbox", err) 94 } 95 } 96 }) 97 } 98 99 d.output("Images:") 100 images, err := d.store.ImagesInUse() 101 switch { 102 case err != nil: 103 d.outputError("can't list images", err) 104 case len(images) == 0: 105 d.output("no images found") 106 default: 107 d.withAddedIndent(func() { 108 for image := range images { 109 d.output(image) 110 } 111 }) 112 } 113 } 114 115 func (d *metadataDumper) dumpSandbox(podID string, sandbox *types.PodSandboxInfo) error { 116 d.output("Sandbox ID: %v", podID) 117 d.withAddedIndent(func() { 118 d.outputYaml(sandbox) 119 120 d.output("Containers:") 121 containers, err := d.store.ListPodContainers(podID) 122 switch { 123 case err != nil: 124 d.outputError("can't retrieve the list of containers", err) 125 case len(containers) == 0: 126 d.output("no containers found") 127 default: 128 d.withAddedIndent(func() { 129 for _, cmeta := range containers { 130 d.output("Container ID: %s", cmeta.GetID()) 131 if cinfo, err := cmeta.Retrieve(); err != nil { 132 d.outputError("can't retrieve container metadata", err) 133 } else { 134 d.withAddedIndent(func() { d.outputYaml(cinfo) }) 135 } 136 } 137 }) 138 } 139 }) 140 141 return nil 142 } 143 144 // GetMetadataDumpSource returns a Source that dumps Virtlet metadata. 145 func GetMetadataDumpSource(store Store) diag.Source { 146 return diag.NewSimpleTextSource("txt", func() (string, error) { 147 var out bytes.Buffer 148 dumper := newMetadataDumper(store, &out) 149 dumper.dump() 150 return out.String(), nil 151 }) 152 }