yunion.io/x/cloudmux@v0.3.10-0-alpha.1/cmd/cmx/shell/helper.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package shell 16 17 import ( 18 "net/http" 19 "net/url" 20 "os" 21 22 "golang.org/x/net/http/httpproxy" 23 24 "yunion.io/x/jsonutils" 25 "yunion.io/x/log" 26 "yunion.io/x/pkg/errors" 27 28 "yunion.io/x/cloudmux/pkg/cloudprovider" 29 "yunion.io/x/cloudmux/pkg/cloudprovider/generic" 30 "yunion.io/x/onecloud/pkg/util/shellutils" 31 "yunion.io/x/onecloud/pkg/util/printutils" 32 ) 33 34 var ( 35 CommandTable = &shellutils.CommandTable 36 R = shellutils.R 37 PrintList = printutils.PrintInterfaceList 38 PrintObject = printutils.PrintInterfaceObject 39 PrintGetterList = printutils.PrintGetterList 40 ) 41 42 type ICloudProvider interface { 43 GetProvider() cloudprovider.ICloudProvider 44 GetDefaultRegionId() string 45 } 46 47 type cloudProvider struct { 48 provider cloudprovider.ICloudProvider 49 globalOpt *GlobalOptions 50 } 51 52 func NewCloudProvider(opt *GlobalOptions) (ICloudProvider, error) { 53 if len(opt.AccessKey) == 0 { 54 return nil, errors.Errorf("Missing accessKey") 55 } 56 57 if len(opt.Secret) == 0 { 58 return nil, errors.Errorf("Missing secret") 59 } 60 61 cfg := &httpproxy.Config{ 62 HTTPProxy: os.Getenv("HTTP_PROXY"), 63 HTTPSProxy: os.Getenv("HTTPS_PROXY"), 64 NoProxy: os.Getenv("NO_PROXY"), 65 } 66 cfgProxyFunc := cfg.ProxyFunc() 67 proxyFunc := func(req *http.Request) (*url.URL, error) { 68 return cfgProxyFunc(req.URL) 69 } 70 71 factory, err := cloudprovider.GetProviderFactory(opt.Provider) 72 if err != nil { 73 return nil, errors.Wrapf(err, "GetProviderFactory") 74 } 75 76 p, err := factory.GetProvider(cloudprovider.ProviderConfig{ 77 URL: opt.CloudEnv, 78 Account: opt.AccessKey, 79 Secret: opt.Secret, 80 ProxyFunc: proxyFunc, 81 DefaultRegion: opt.Region, 82 Debug: opt.Debug, 83 }) 84 85 if err != nil { 86 return nil, errors.Wrap(err, "GetProvider") 87 } 88 89 var dr cloudprovider.ICloudRegion = nil 90 91 if opt.Region != "" { 92 dr, _ = generic.GetResourceByIdOrName(p.GetIRegions(), opt.Region) 93 if dr == nil { 94 rs := p.GetIRegions() 95 regions := make([]string, len(rs)) 96 for i := range rs { 97 regions[i] = rs[i].GetId() 98 } 99 return nil, errors.Errorf("Not found region by %q of %q, choose one of:\n%s", opt.Region, opt.Provider, jsonutils.Marshal(regions).PrettyString()) 100 } 101 } 102 103 return &cloudProvider{ 104 provider: p, 105 globalOpt: opt, 106 }, nil 107 } 108 109 func (p *cloudProvider) GetProvider() cloudprovider.ICloudProvider { 110 return p.provider 111 } 112 113 func (p *cloudProvider) GetDefaultRegionId() string { 114 return p.globalOpt.Region 115 } 116 117 func getResources[T cloudprovider.ICloudResource]( 118 resType string, 119 nf func() ([]T, error), 120 specifyIdOrName string, 121 mustMatch bool) ([]T, error) { 122 objs, err := nf() 123 if err != nil { 124 return nil, errors.Wrapf(err, "get %q resources", resType) 125 } 126 127 if specifyIdOrName == "" { 128 if mustMatch { 129 return nil, errors.Errorf("Use '--%s' to specify %s", resType, resType) 130 } else { 131 return objs, nil 132 } 133 } 134 obj, err := generic.GetResourceByIdOrName(objs, specifyIdOrName) 135 if err != nil { 136 if errors.Cause(err) == cloudprovider.ErrNotFound { 137 return nil, errors.Wrapf(err, "%s %s not found", resType, specifyIdOrName) 138 } 139 } 140 return []T{obj}, nil 141 } 142 143 func iterResources[T cloudprovider.ICloudResource]( 144 resType string, 145 nf func() ([]T, error), 146 specifyIdOrName string, 147 mustMatch bool, 148 ef func(T) error, 149 ) error { 150 op, err := generic.NewOperator(func() ([]T, error) { 151 return getResources(resType, nf, specifyIdOrName, mustMatch) 152 }) 153 if err != nil { 154 return err 155 } 156 return op.Iter(func(t T) error { 157 log.Infof("With %s %q", resType, t.GetGlobalId()) 158 return ef(t) 159 }, false) 160 } 161 162 // func regionR[OPT any](opts OPT, command string, desc string, requireDefaultRegion bool, cb func(cloudprovider.ICloudRegion, OPT) error) { 163 // R(opts, command, desc, func(cli ICloudProvider, args OPT) error { 164 // return iterResources( 165 // "region", 166 // func() ([]cloudprovider.ICloudRegion, error) { 167 // return cli.GetProvider().GetIRegions(), nil 168 // }, 169 // cli.GetDefaultRegionId(), 170 // requireDefaultRegion, 171 // func(region cloudprovider.ICloudRegion) error { 172 // if err := cb(region, args); err != nil { 173 // return err 174 // } 175 // return nil 176 // }, 177 // ) 178 // }) 179 // } 180 // 181 // func RegionR[T any](opts T, command string, desc string, cb func(cloudprovider.ICloudRegion, T) error) { 182 // regionR(opts, command, desc, true, cb) 183 // } 184 // 185 // func RegionRList[T any](opts T, command string, desc string, cb func(cloudprovider.ICloudRegion, T) error) { 186 // regionR(opts, command, desc, false, cb) 187 // } 188 // 189 // func zoneR[T IZoneBaseOptions](opts T, command string, desc string, requireZone bool, cb func(cloudprovider.ICloudZone, T) error) { 190 // RegionRList(opts, command, desc, func(region cloudprovider.ICloudRegion, opts T) error { 191 // return iterResources( 192 // "zone", 193 // region.GetIZones, 194 // opts.GetZoneId(), 195 // requireZone, 196 // func(zone cloudprovider.ICloudZone) error { 197 // if err := cb(zone, opts); err != nil { 198 // return err 199 // } 200 // return nil 201 // }, 202 // ) 203 // }) 204 // } 205 // 206 // func ZoneRList[T IZoneBaseOptions](opts T, command string, desc string, cb func(cloudprovider.ICloudZone, T) error) { 207 // zoneR(opts, command, desc, false, cb) 208 // } 209 // 210 // func ZoneR[T IZoneBaseOptions](opts T, command string, desc string, cb func(cloudprovider.ICloudZone, T) error) { 211 // zoneR(opts, command, desc, true, cb) 212 // } 213 // 214 // func hostR[T IHostBaseOptions](opts T, command string, desc string, requireHost bool, cb func(cloudprovider.ICloudHost, T) error) { 215 // ZoneRList(opts, command, desc, func(zone cloudprovider.ICloudZone, opts T) error { 216 // return iterResources( 217 // "host", 218 // zone.GetIHosts, 219 // opts.GetHostId(), 220 // requireHost, 221 // func(host cloudprovider.ICloudHost) error { 222 // if err := cb(host, opts); err != nil { 223 // return err 224 // } 225 // return nil 226 // }, 227 // ) 228 // }) 229 // } 230 // 231 // func HostRList[T IHostBaseOptions](opts T, command string, desc string, cb func(cloudprovider.ICloudHost, T) error) { 232 // hostR(opts, command, desc, false, cb) 233 // } 234 // 235 // func HostR[T IHostBaseOptions](opts T, command string, desc string, cb func(cloudprovider.ICloudHost, T) error) { 236 // hostR(opts, command, desc, true, cb) 237 // }