github.com/vmware/govmomi@v0.51.0/cli/flags/datacenter.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 flags 6 7 import ( 8 "context" 9 "flag" 10 "fmt" 11 "os" 12 "strings" 13 14 "github.com/vmware/govmomi/find" 15 "github.com/vmware/govmomi/object" 16 "github.com/vmware/govmomi/property" 17 "github.com/vmware/govmomi/vim25/types" 18 ) 19 20 type DatacenterFlag struct { 21 common 22 23 *ClientFlag 24 *OutputFlag 25 26 Name string 27 dc *object.Datacenter 28 finder *find.Finder 29 err error 30 } 31 32 var datacenterFlagKey = flagKey("datacenter") 33 34 func NewDatacenterFlag(ctx context.Context) (*DatacenterFlag, context.Context) { 35 if v := ctx.Value(datacenterFlagKey); v != nil { 36 return v.(*DatacenterFlag), ctx 37 } 38 39 v := &DatacenterFlag{} 40 v.ClientFlag, ctx = NewClientFlag(ctx) 41 v.OutputFlag, ctx = NewOutputFlag(ctx) 42 ctx = context.WithValue(ctx, datacenterFlagKey, v) 43 return v, ctx 44 } 45 46 func (flag *DatacenterFlag) Register(ctx context.Context, f *flag.FlagSet) { 47 flag.RegisterOnce(func() { 48 flag.ClientFlag.Register(ctx, f) 49 flag.OutputFlag.Register(ctx, f) 50 51 env := "GOVC_DATACENTER" 52 value := os.Getenv(env) 53 usage := fmt.Sprintf("Datacenter [%s]", env) 54 f.StringVar(&flag.Name, "dc", value, usage) 55 }) 56 } 57 58 func (flag *DatacenterFlag) Process(ctx context.Context) error { 59 return flag.ProcessOnce(func() error { 60 if err := flag.ClientFlag.Process(ctx); err != nil { 61 return err 62 } 63 if err := flag.OutputFlag.Process(ctx); err != nil { 64 return err 65 } 66 return nil 67 }) 68 } 69 70 func (flag *DatacenterFlag) Finder(all ...bool) (*find.Finder, error) { 71 if flag.finder != nil { 72 return flag.finder, nil 73 } 74 75 c, err := flag.Client() 76 if err != nil { 77 return nil, err 78 } 79 80 allFlag := false 81 if len(all) == 1 { 82 allFlag = all[0] 83 } 84 finder := find.NewFinder(c, allFlag) 85 86 // Datacenter is not required (ls command for example). 87 // Set for relative func if dc flag is given or 88 // if there is a single (default) Datacenter 89 ctx := context.TODO() 90 if flag.Name == "" { 91 flag.dc, flag.err = finder.DefaultDatacenter(ctx) 92 } else { 93 if flag.dc, err = finder.Datacenter(ctx, flag.Name); err != nil { 94 return nil, err 95 } 96 } 97 98 finder.SetDatacenter(flag.dc) 99 100 flag.finder = finder 101 102 return flag.finder, nil 103 } 104 105 func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) { 106 if flag.dc != nil { 107 return flag.dc, nil 108 } 109 110 _, err := flag.Finder() 111 if err != nil { 112 return nil, err 113 } 114 115 if flag.err != nil { 116 // Should only happen if no dc is specified and len(dcs) > 1 117 return nil, flag.err 118 } 119 120 return flag.dc, err 121 } 122 123 func (flag *DatacenterFlag) DatacenterIfSpecified() (*object.Datacenter, error) { 124 if flag.Name == "" { 125 return nil, nil 126 } 127 return flag.Datacenter() 128 } 129 130 func (flag *DatacenterFlag) ManagedObject(ctx context.Context, arg string) (types.ManagedObjectReference, error) { 131 var ref types.ManagedObjectReference 132 133 finder, err := flag.Finder() 134 if err != nil { 135 return ref, err 136 } 137 138 if ref.FromString(arg) { 139 if strings.HasPrefix(ref.Type, "com.vmware.content.") { 140 return ref, nil // special case for content library 141 } 142 pc := property.DefaultCollector(flag.client) 143 var content []types.ObjectContent 144 err = pc.RetrieveOne(ctx, ref, []string{"name"}, &content) 145 if err == nil { 146 return ref, nil 147 } 148 } 149 150 l, err := finder.ManagedObjectList(ctx, arg) 151 if err != nil { 152 return ref, err 153 } 154 155 switch len(l) { 156 case 0: 157 return ref, fmt.Errorf("%s not found", arg) 158 case 1: 159 return l[0].Object.Reference(), nil 160 default: 161 var objs []types.ManagedObjectReference 162 for _, o := range l { 163 objs = append(objs, o.Object.Reference()) 164 } 165 return ref, fmt.Errorf("%d objects match %q: %s (unique inventory path required)", len(l), arg, objs) 166 } 167 } 168 169 func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) { 170 var refs []types.ManagedObjectReference 171 172 c, err := flag.Client() 173 if err != nil { 174 return nil, err 175 } 176 177 if len(args) == 0 { 178 refs = append(refs, c.ServiceContent.RootFolder) 179 return refs, nil 180 } 181 182 finder, err := flag.Finder() 183 if err != nil { 184 return nil, err 185 } 186 187 for _, arg := range args { 188 elements, err := finder.ManagedObjectList(ctx, arg) 189 if err != nil { 190 return nil, err 191 } 192 193 if len(elements) == 0 { 194 return nil, fmt.Errorf("object '%s' not found", arg) 195 } 196 197 if len(elements) > 1 && !strings.Contains(arg, "/") { 198 return nil, fmt.Errorf("%q must be qualified with a path", arg) 199 } 200 201 for _, e := range elements { 202 refs = append(refs, e.Object.Reference()) 203 } 204 } 205 206 return refs, nil 207 }