vSphere Cloud Provider: update vmware/gomvomi godeps

This commit is contained in:
Doug MacEachern
2018-05-14 14:09:20 -07:00
parent 83768d286c
commit c340f6f9a4
55 changed files with 8733 additions and 596 deletions

View File

@@ -28,6 +28,7 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/http/cookiejar"
@@ -53,17 +54,9 @@ type RoundTripper interface {
}
const (
DefaultVimNamespace = "urn:vim25"
DefaultVimVersion = "6.5"
DefaultMinVimVersion = "5.5"
SessionCookieName = "vmware_soap_session"
SessionCookieName = "vmware_soap_session"
)
type header struct {
Cookie string `xml:"vcSessionCookie,omitempty"`
ID string `xml:"operationID,omitempty"`
}
type Client struct {
http.Client
@@ -71,7 +64,6 @@ type Client struct {
k bool // Named after curl's -k flag
d *debugContainer
t *http.Transport
p *url.URL
hostsMu sync.Mutex
hosts map[string]string
@@ -149,20 +141,33 @@ func NewClient(u *url.URL, insecure bool) *Client {
c.u = c.URL()
c.u.User = nil
c.Namespace = DefaultVimNamespace
c.Version = DefaultVimVersion
return &c
}
// NewServiceClient creates a NewClient with the given URL.Path and namespace.
func (c *Client) NewServiceClient(path string, namespace string) *Client {
u := c.URL()
u.Path = path
vc := c.URL()
u, err := url.Parse(path)
if err != nil {
log.Panicf("url.Parse(%q): %s", path, err)
}
if u.Host == "" {
u.Scheme = vc.Scheme
u.Host = vc.Host
}
client := NewClient(u, c.k)
client.Namespace = "urn:" + namespace
if cert := c.Certificate(); cert != nil {
client.SetCertificate(*cert)
}
client.Namespace = namespace
// Copy the trusted thumbprints
c.hostsMu.Lock()
for k, v := range c.hosts {
client.hosts[k] = v
}
c.hostsMu.Unlock()
// Copy the cookies
client.Client.Jar.SetCookies(u, c.Client.Jar.Cookies(u))
@@ -175,6 +180,9 @@ func (c *Client) NewServiceClient(path string, namespace string) *Client {
}
}
// Copy any query params (e.g. GOVMOMI_TUNNEL_PROXY_PORT used in testing)
client.u.RawQuery = vc.RawQuery
return client
}
@@ -346,19 +354,33 @@ func splitHostPort(host string) (string, string) {
const sdkTunnel = "sdkTunnel:8089"
func (c *Client) Certificate() *tls.Certificate {
certs := c.t.TLSClientConfig.Certificates
if len(certs) == 0 {
return nil
}
return &certs[0]
}
func (c *Client) SetCertificate(cert tls.Certificate) {
t := c.Client.Transport.(*http.Transport)
// Extension certificate
// Extension or HoK certificate
t.TLSClientConfig.Certificates = []tls.Certificate{cert}
}
// Tunnel returns a Client configured to proxy requests through vCenter's http port 80,
// to the SDK tunnel virtual host. Use of the SDK tunnel is required by LoginExtensionByCertificate()
// and optional for other methods.
func (c *Client) Tunnel() *Client {
tunnel := c.NewServiceClient(c.u.Path, c.Namespace)
t := tunnel.Client.Transport.(*http.Transport)
// Proxy to vCenter host on port 80
host, _ := splitHostPort(c.u.Host)
host := tunnel.u.Hostname()
// Should be no reason to change the default port other than testing
key := "GOVMOMI_TUNNEL_PROXY_PORT"
port := c.URL().Query().Get(key)
port := tunnel.URL().Query().Get(key)
if port == "" {
port = os.Getenv(key)
}
@@ -367,20 +389,14 @@ func (c *Client) SetCertificate(cert tls.Certificate) {
host += ":" + port
}
c.p = &url.URL{
t.Proxy = http.ProxyURL(&url.URL{
Scheme: "http",
Host: host,
}
t.Proxy = func(r *http.Request) (*url.URL, error) {
// Only sdk requests should be proxied
if r.URL.Path == "/sdk" {
return c.p, nil
}
return http.ProxyFromEnvironment(r)
}
})
// Rewrite url Host to use the sdk tunnel, required for a certificate request.
c.u.Host = sdkTunnel
tunnel.u.Host = sdkTunnel
return tunnel
}
func (c *Client) URL() *url.URL {
@@ -426,21 +442,41 @@ func (c *Client) do(ctx context.Context, req *http.Request) (*http.Response, err
return c.Client.Do(req.WithContext(ctx))
}
// Signer can be implemented by soap.Header.Security to sign requests.
// If the soap.Header.Security field is set to an implementation of Signer via WithHeader(),
// then Client.RoundTrip will call Sign() to marshal the SOAP request.
type Signer interface {
Sign(Envelope) ([]byte, error)
}
type headerContext struct{}
// WithHeader can be used to modify the outgoing request soap.Header fields.
func (c *Client) WithHeader(ctx context.Context, header Header) context.Context {
return context.WithValue(ctx, headerContext{}, header)
}
func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error {
var err error
var b []byte
reqEnv := Envelope{Body: reqBody}
resEnv := Envelope{Body: resBody}
h := &header{
Cookie: c.cookie,
h, ok := ctx.Value(headerContext{}).(Header)
if !ok {
h = Header{}
}
// We added support for OperationID before soap.Header was exported.
if id, ok := ctx.Value(types.ID{}).(string); ok {
h.ID = id
}
reqEnv.Header = h
h.Cookie = c.cookie
if h.Cookie != "" || h.ID != "" || h.Security != nil {
reqEnv.Header = &h // XML marshal header only if a field is set
}
// Create debugging context for this round trip
d := c.d.newRoundTrip()
@@ -448,9 +484,16 @@ func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error
defer d.done()
}
b, err := xml.Marshal(reqEnv)
if err != nil {
panic(err)
if signer, ok := h.Security.(Signer); ok {
b, err = signer.Sign(reqEnv)
if err != nil {
return err
}
} else {
b, err = xml.Marshal(reqEnv)
if err != nil {
panic(err)
}
}
rawReqBody := io.MultiReader(strings.NewReader(xml.Header), bytes.NewReader(b))
@@ -462,8 +505,13 @@ func (c *Client) RoundTrip(ctx context.Context, reqBody, resBody HasFault) error
req = req.WithContext(ctx)
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
soapAction := fmt.Sprintf("%s/%s", c.Namespace, c.Version)
req.Header.Set(`SOAPAction`, soapAction)
action := h.Action
if action == "" {
action = fmt.Sprintf("%s/%s", c.Namespace, c.Version)
}
req.Header.Set(`SOAPAction`, action)
if c.UserAgent != "" {
req.Header.Set(`User-Agent`, c.UserAgent)
}

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2014 VMware, Inc. All Rights Reserved.
Copyright (c) 2014-2018 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.
@@ -21,9 +21,17 @@ import (
"github.com/vmware/govmomi/vim25/xml"
)
// Header includes optional soap Header fields.
type Header struct {
Action string `xml:"-"` // Action is the 'SOAPAction' HTTP header value. Defaults to "Client.Namespace/Client.Version".
Cookie string `xml:"vcSessionCookie,omitempty"` // Cookie is a vCenter session cookie that can be used with other SDK endpoints (e.g. pbm).
ID string `xml:"operationID,omitempty"` // ID is the operationID used by ESX/vCenter logging for correlation.
Security interface{} `xml:",omitempty"` // Security is used for SAML token authentication and request signing.
}
type Envelope struct {
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
Header interface{} `xml:",omitempty"`
XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
Header *Header `xml:"http://schemas.xmlsoap.org/soap/envelope/ Header,omitempty"`
Body interface{}
}