diff --git a/govc/main.go b/govc/main.go index ff6f66c64..6e028cc4b 100644 --- a/govc/main.go +++ b/govc/main.go @@ -88,6 +88,7 @@ import ( _ "github.com/vmware/govmomi/govc/task" _ "github.com/vmware/govmomi/govc/vapp" _ "github.com/vmware/govmomi/govc/vcsa/log" + _ "github.com/vmware/govmomi/govc/vcsa/proxy" _ "github.com/vmware/govmomi/govc/version" _ "github.com/vmware/govmomi/govc/vm" _ "github.com/vmware/govmomi/govc/vm/disk" diff --git a/govc/vcsa/proxy/proxy.go b/govc/vcsa/proxy/proxy.go new file mode 100644 index 000000000..a142bf836 --- /dev/null +++ b/govc/vcsa/proxy/proxy.go @@ -0,0 +1,116 @@ +/* +Copyright (c) 2021 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package net + +import ( + "context" + "flag" + "fmt" + "io" + "strings" + "text/tabwriter" + + "github.com/vmware/govmomi/govc/cli" + "github.com/vmware/govmomi/govc/flags" + vnetworking "github.com/vmware/govmomi/vapi/appliance/networking" +) + +type info struct { + *flags.ClientFlag + *flags.OutputFlag +} + +func init() { + cli.Register("vcsa.net.proxy.info", &info{}) +} + +func (cmd *info) Register(ctx context.Context, f *flag.FlagSet) { + cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) + cmd.ClientFlag.Register(ctx, f) + + cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) + cmd.OutputFlag.Register(ctx, f) +} + +func (cmd *info) Process(ctx context.Context) error { + if err := cmd.ClientFlag.Process(ctx); err != nil { + return err + } + if err := cmd.OutputFlag.Process(ctx); err != nil { + return err + } + return nil +} + +func (cmd *info) Description() string { + return `Retrieve the VC networking proxy configuration + +Examples: + govc vcsa.net.proxy.info` +} + +type proxyResult struct { + proxy *vnetworking.ProxyList + noProxy []string +} + +func (cmd *info) Run(ctx context.Context, f *flag.FlagSet) error { + c, err := cmd.RestClient() + if err != nil { + return err + } + + fwd := vnetworking.NewManager(c) + + proxyRes, err := fwd.ProxyList(ctx) + if err != nil { + fmt.Println(err) + return nil + } + + noProxyRes, err := fwd.NoProxy(ctx) + if err != nil { + fmt.Println(err) + return nil + } + + return cmd.WriteResult(&proxyResult{proxyRes, noProxyRes}) +} + +func (res proxyResult) Write(w io.Writer) error { + tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) + printProxyConfig("HTTP", res.proxy.Http, tw) + printProxyConfig("HTTPS", res.proxy.Https, tw) + printProxyConfig("FTP", res.proxy.Ftp, tw) + fmt.Fprintf(tw, "No Proxy addresses:\t%s\n", strings.Join(res.noProxy, ", ")) + + return tw.Flush() +} + +func printProxyConfig(proxyName string, proxyProtocolConfig vnetworking.Proxy, w io.Writer) { + if !proxyProtocolConfig.Enabled { + fmt.Fprintf(w, "%s proxy:\tDisabled\n", proxyName) + return + } + + fmt.Fprintf(w, "%s proxy:\tEnabled\n", proxyName) + fmt.Fprintf(w, "\tServer:\t%s\n", proxyProtocolConfig.Server) + fmt.Fprintf(w, "\tPort:\t%d\n", proxyProtocolConfig.Port) + if proxyProtocolConfig.Username != "" { + fmt.Fprintf(w, "\tUsername:\t%s\n", proxyProtocolConfig.Username) + } +} diff --git a/vapi/appliance/networking/proxy.go b/vapi/appliance/networking/proxy.go new file mode 100644 index 000000000..556e1e76b --- /dev/null +++ b/vapi/appliance/networking/proxy.go @@ -0,0 +1,90 @@ +/* +Copyright (c) 2021 VMware, Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0. +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package networking + +import ( + "context" + "net/http" + + "github.com/vmware/govmomi/vapi/rest" +) + +const applianceProxyConfigPath = "/appliance/networking/proxy" +const applianceNoProxyConfigPath = "/appliance/networking/noproxy" + +// Manager provides convenience methods to configure appliance proxy. +type Manager struct { + *rest.Client +} + +// NewManager creates a new Manager with the given client +func NewManager(client *rest.Client) *Manager { + return &Manager{ + Client: client, + } +} + +// Proxy represents configuration for specific proxy - ftp, http, https. +type Proxy struct { + Server string `json:"server,omitempty"` + Port int `json:"port,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + Enabled bool `json:"enabled,omitempty"` +} + +// ProxyList represents configuration for vcenter proxy. +type ProxyList struct { + Ftp Proxy `json:"ftp,omitempty"` + Http Proxy `json:"http,omitempty"` + Https Proxy `json:"https,omitempty"` +} + +// ProxyList returns all Proxy configuration. +func (m *Manager) ProxyList(ctx context.Context) (*ProxyList, error) { + var res ProxyList + var rawRes []struct { + Key string + Value Proxy + } + + r := m.Resource(applianceProxyConfigPath) + err := m.Do(ctx, r.Request(http.MethodGet), &rawRes) + if err != nil { + return &res, err + } + + for _, c := range rawRes { + switch c.Key { + case "http": + res.Http = c.Value + case "https": + res.Https = c.Value + case "ftp": + res.Ftp = c.Value + } + } + + return &res, nil +} + +// NoProxy returns all excluded servers for proxying. +func (m *Manager) NoProxy(ctx context.Context) ([]string, error) { + r := m.Resource(applianceNoProxyConfigPath) + var res []string + return res, m.Do(ctx, r.Request(http.MethodGet), &res) +}