github.com/vmware/govmomi@v0.51.0/cli/library/info.go (about) 1 // © Broadcom. All Rights Reserved. 2 // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. 3 // SPDX-License-Identifier: Apache-2.0 4 5 package library 6 7 import ( 8 "context" 9 "encoding/json" 10 "flag" 11 "fmt" 12 "io" 13 "text/tabwriter" 14 "time" 15 16 "github.com/vmware/govmomi/cli" 17 "github.com/vmware/govmomi/cli/flags" 18 "github.com/vmware/govmomi/object" 19 "github.com/vmware/govmomi/units" 20 "github.com/vmware/govmomi/vapi/library" 21 "github.com/vmware/govmomi/vapi/library/finder" 22 ) 23 24 type info struct { 25 *flags.ClientFlag 26 *flags.OutputFlag 27 *flags.DatacenterFlag 28 29 long bool 30 link bool 31 url bool 32 stor bool 33 Stor bool 34 35 pathFinder *finder.PathFinder 36 } 37 38 func init() { 39 cli.Register("library.info", &info{}) 40 } 41 42 func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) { 43 cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) 44 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 45 cmd.ClientFlag.Register(ctx, f) 46 cmd.OutputFlag.Register(ctx, f) 47 cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx) 48 cmd.DatacenterFlag.Register(ctx, f) 49 50 f.BoolVar(&cmd.long, "l", false, "Long listing format") 51 f.BoolVar(&cmd.link, "L", false, "List Datastore path only") 52 f.BoolVar(&cmd.url, "U", false, "List pub/sub URL(s) only") 53 f.BoolVar(&cmd.stor, "s", false, "Include file specific storage details") 54 if cli.ShowUnreleased() { 55 f.BoolVar(&cmd.Stor, "S", false, "Include file specific storage details (resolved)") 56 } 57 } 58 59 func (cmd *info) Process(ctx context.Context) error { 60 if err := cmd.ClientFlag.Process(ctx); err != nil { 61 return err 62 } 63 return nil 64 } 65 66 func (cmd *info) Description() string { 67 return `Display library information. 68 69 Note: the '-s' flag only applies to files, not items or the library itself. 70 71 Examples: 72 govc library.info 73 govc library.info /lib1 74 govc library.info -l /lib1 | grep Size: 75 govc library.info /lib1/item1 76 govc library.info /lib1/item1/ 77 govc library.info */ 78 govc library.info -L /lib1/item1/file1 # file path relative to Datastore 79 govc library.info -L -l /lib1/item1/file1 # file path including Datastore 80 govc library.info -json | jq . 81 govc library.info -json /lib1/item1 | jq .` 82 } 83 84 type infoResultsWriter struct { 85 Result []finder.FindResult `json:"result"` 86 m *library.Manager 87 cmd *info 88 ctx context.Context 89 } 90 91 func (r infoResultsWriter) MarshalJSON() ([]byte, error) { 92 return json.Marshal(r.Result) 93 } 94 95 func (r infoResultsWriter) Dump() any { 96 res := make([]any, len(r.Result)) 97 for i := range r.Result { 98 res[i] = r.Result[0].GetResult() 99 } 100 return res 101 } 102 103 func (r infoResultsWriter) Write(w io.Writer) error { 104 if r.cmd.link { 105 for _, j := range r.Result { 106 p, err := r.cmd.pathFinder.Path(context.Background(), j) 107 if err != nil { 108 return err 109 } 110 if !r.cmd.long { 111 var path object.DatastorePath 112 path.FromString(p) 113 p = path.Path 114 } 115 fmt.Fprintln(w, p) 116 } 117 return nil 118 } 119 120 tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) 121 defer tw.Flush() 122 for _, j := range r.Result { 123 switch t := j.GetResult().(type) { 124 case library.Library: 125 if err := r.writeLibrary(tw, t, j); err != nil { 126 return err 127 } 128 case library.Item: 129 if err := r.writeItem(tw, t, j); err != nil { 130 return err 131 } 132 case library.File: 133 if err := r.writeFile(tw, t, j); err != nil { 134 return err 135 } 136 } 137 tw.Flush() 138 } 139 return nil 140 } 141 142 func (r infoResultsWriter) writeLibrary( 143 w io.Writer, v library.Library, res finder.FindResult) error { 144 145 published := v.Publication != nil && *v.Publication.Published 146 147 if r.cmd.url { 148 switch { 149 case v.Subscription != nil: 150 _, _ = fmt.Fprintf(w, "%s\n", v.Subscription.SubscriptionURL) 151 case published: 152 _, _ = fmt.Fprintf(w, "%s\n", v.Publication.PublishURL) 153 } 154 155 return nil 156 } 157 158 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 159 fmt.Fprintf(w, " ID:\t%s\n", v.ID) 160 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 161 if v.Description != nil { 162 fmt.Fprintf(w, " Description:\t%s\n", *v.Description) 163 } 164 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 165 fmt.Fprintf(w, " Created:\t%s\n", v.CreationTime.Format(time.ANSIC)) 166 fmt.Fprintf(w, " Security Policy ID\t%s\n", v.SecurityPolicyID) 167 fmt.Fprintf(w, " StorageBackings:\t\n") 168 for _, d := range v.Storage { 169 fmt.Fprintf(w, " DatastoreID:\t%s\n", d.DatastoreID) 170 fmt.Fprintf(w, " Type:\t%s\n", d.Type) 171 } 172 if r.cmd.long { 173 p, err := r.cmd.pathFinder.Path(r.ctx, res) 174 if err != nil { 175 return err 176 } 177 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 178 items, err := r.m.GetLibraryItems(r.ctx, v.ID) 179 if err != nil { 180 return err 181 } 182 var size int64 183 for i := range items { 184 size += items[i].Size 185 } 186 fmt.Fprintf(w, " Size:\t%s\n", units.ByteSize(size)) 187 fmt.Fprintf(w, " Items:\t%d\n", len(items)) 188 } 189 if v.Subscription != nil { 190 dl := "All" 191 if v.Subscription.OnDemand != nil && *v.Subscription.OnDemand { 192 dl = "On Demand" 193 } 194 195 fmt.Fprintf(w, " Subscription:\t\n") 196 fmt.Fprintf(w, " AutoSync:\t%t\n", *v.Subscription.AutomaticSyncEnabled) 197 fmt.Fprintf(w, " URL:\t%s\n", v.Subscription.SubscriptionURL) 198 fmt.Fprintf(w, " Auth:\t%s\n", v.Subscription.AuthenticationMethod) 199 fmt.Fprintf(w, " Download:\t%s\n", dl) 200 } 201 if published { 202 fmt.Fprintf(w, " Publication:\t\n") 203 fmt.Fprintf(w, " URL:\t%s\n", v.Publication.PublishURL) 204 fmt.Fprintf(w, " Auth:\t%s\n", v.Publication.AuthenticationMethod) 205 } 206 return nil 207 } 208 209 func (r infoResultsWriter) writeItem( 210 w io.Writer, v library.Item, res finder.FindResult) error { 211 212 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 213 fmt.Fprintf(w, " ID:\t%s\n", v.ID) 214 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 215 if v.Description != nil { 216 fmt.Fprintf(w, " Description:\t%s\n", *v.Description) 217 } 218 fmt.Fprintf(w, " Type:\t%s\n", v.Type) 219 fmt.Fprintf(w, " Size:\t%s\n", units.ByteSize(v.Size)) 220 fmt.Fprintf(w, " Cached:\t%t\n", v.Cached) 221 fmt.Fprintf(w, " Created:\t%s\n", v.CreationTime.Format(time.ANSIC)) 222 fmt.Fprintf(w, " Modified:\t%s\n", v.LastModifiedTime.Format(time.ANSIC)) 223 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 224 if v.SecurityCompliance != nil { 225 fmt.Fprintf(w, " Security Compliance:\t%t\n", *v.SecurityCompliance) 226 } 227 if v.CertificateVerification != nil { 228 fmt.Fprintf(w, " Certificate Status:\t%s\n", v.CertificateVerification.Status) 229 } 230 if r.cmd.long { 231 p, err := r.cmd.pathFinder.Path(r.ctx, res) 232 if err != nil { 233 return err 234 } 235 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 236 } 237 238 return nil 239 } 240 241 func (r infoResultsWriter) writeFile( 242 w io.Writer, v library.File, res finder.FindResult) error { 243 244 size := "-" 245 if v.Size != nil { 246 size = units.ByteSize(*v.Size).String() 247 } 248 fmt.Fprintf(w, "Name:\t%s\n", v.Name) 249 fmt.Fprintf(w, " Path:\t%s\n", res.GetPath()) 250 fmt.Fprintf(w, " Size:\t%s\n", size) 251 fmt.Fprintf(w, " Version:\t%s\n", v.Version) 252 253 if r.cmd.long { 254 p, err := r.cmd.pathFinder.Path(r.ctx, res) 255 if err != nil { 256 return err 257 } 258 fmt.Fprintf(w, " Datastore Path:\t%s\n", p) 259 } 260 if r.cmd.stor || r.cmd.Stor { 261 label := "Storage URI" 262 s, err := r.m.GetLibraryItemStorage(r.ctx, res.GetParent().GetID(), v.Name) 263 if err != nil { 264 return err 265 } 266 if r.cmd.Stor { 267 label = "Resolved URI" 268 err = r.cmd.pathFinder.ResolveLibraryItemStorage(r.ctx, nil, nil, s) 269 if err != nil { 270 return err 271 } 272 } 273 for i := range s { 274 for _, uri := range s[i].StorageURIs { 275 fmt.Fprintf(w, " %s:\t%s\n", label, uri) 276 } 277 } 278 } 279 280 return nil 281 } 282 283 func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error { 284 c, err := cmd.RestClient() 285 if err != nil { 286 return err 287 } 288 vc, err := cmd.Client() 289 if err != nil { 290 return err 291 } 292 293 m := library.NewManager(c) 294 cmd.pathFinder = finder.NewPathFinder(m, vc) 295 finder := finder.NewFinder(m) 296 findResults, err := finder.Find(ctx, f.Args()...) 297 if err != nil { 298 return err 299 } 300 301 return cmd.WriteResult(&infoResultsWriter{findResults, m, cmd, ctx}) 302 }