diff --git a/go.mod b/go.mod index 0c9b2777bc..58f02ab0b6 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/golang-plus/uuid v1.0.0 github.com/golang/mock v1.4.4 github.com/google/gopacket v1.1.17 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.6.0 github.com/googollee/go-socket.io v0.0.0-20181214084611-0ad7206c347a github.com/gorilla/mux v1.7.0 github.com/gorilla/websocket v1.4.1 @@ -61,7 +61,7 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 github.com/smartystreets/goconvey v1.7.2 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.9.0 github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e github.com/tjfoc/gmsm v1.4.1 github.com/tredoe/osutil/v2 v2.0.0-rc.16 @@ -93,7 +93,7 @@ require ( k8s.io/cri-api v0.22.17 k8s.io/klog/v2 v2.2.0 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240424102057-afce04ea7533 + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240428085659-1415194185cf yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 yunion.io/x/jsonutils v1.0.1-0.20240203102553-4096f103b401 yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91 @@ -240,7 +240,7 @@ require ( github.com/smartystreets/assertions v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.413 // indirect github.com/tencentyun/cos-go-sdk-v5 v0.7.24 // indirect github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e // indirect @@ -248,7 +248,7 @@ require ( github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect github.com/ugorji/go/codec v1.1.7 // indirect - github.com/vmware/govmomi v0.20.1 // indirect + github.com/vmware/govmomi v0.37.1 // indirect github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2 // indirect github.com/volcengine/volc-sdk-golang v1.0.23 // indirect github.com/willf/bitset v1.1.9 // indirect @@ -262,7 +262,7 @@ require ( go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.17.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.8.0 // indirect + golang.org/x/mod v0.9.0 // indirect golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c // indirect golang.org/x/term v0.7.0 // indirect golang.org/x/tools v0.6.0 // indirect diff --git a/go.sum b/go.sum index 183e959646..be32e7882b 100644 --- a/go.sum +++ b/go.sum @@ -366,8 +366,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -390,8 +390,9 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -650,8 +651,8 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8= github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= @@ -694,8 +695,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -704,8 +706,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/syncthing/syncthing v0.14.48-rc.4/go.mod h1:nw3siZwHPA6M8iSfjDCWQ402eqvEIasMQOE8nFOxy7M= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e h1:nt2877sKfojlHCTOBXbpWjBkuWKritFaGIfgQwbQUls= @@ -737,8 +740,8 @@ github.com/vishvananda/netns v0.0.5-0.20240412164733-9469873f4601 h1:eELqkILRCR0 github.com/vishvananda/netns v0.0.5-0.20240412164733-9469873f4601/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmware/govmomi v0.20.1 h1:7b/SeTUB3tER8ZLGLLLH3xcnB2xeuLULXmfPFqPSRZA= -github.com/vmware/govmomi v0.20.1/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/vmware/govmomi v0.37.1 h1:SpI+Ofq+lC1zsLcJ9szLSb7fL4TypReVvUoWIgk2b6U= +github.com/vmware/govmomi v0.37.1/go.mod h1:mtGWtM+YhTADHlCgJBiskSRPOZRsN9MSjPzaZLte/oQ= github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2 h1:FZ7zrUf70YKVuES50mHO3z2VW0K+Arq4uGlDqb+1VA0= github.com/volcengine/ve-tos-golang-sdk/v2 v2.6.2/go.mod h1:IrjK84IJJTuOZOTMv/P18Ydjy/x+ow7fF7q11jAxXLM= github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8= @@ -836,8 +839,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1221,8 +1225,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240424102057-afce04ea7533 h1:byWpucVXxv8DC/5tpzTU2YEZS1d5VHzAEWOeLh3Huek= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240424102057-afce04ea7533/go.mod h1:dsUESXIbXJ+/ywbNClhldOrbPOiBi2udrgOnB/ffoWk= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240428085659-1415194185cf h1:6fJNf4K5NfCHr2WgcPzaF8jfw/YsNw9TilpEO8MeyZI= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20240428085659-1415194185cf/go.mod h1:PkfAKJcu5mic7jyJpT4GxZ8BKIVMa+6eyOP2G94VKAs= yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 h1:v7POYkQwo1XzOxBoIoRVr/k0V9Y5JyjpshlIFa9raug= yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= diff --git a/pkg/hostman/storageman/imagecachemanager_agent.go b/pkg/hostman/storageman/imagecachemanager_agent.go index 5c2069a239..6859bddff2 100644 --- a/pkg/hostman/storageman/imagecachemanager_agent.go +++ b/pkg/hostman/storageman/imagecachemanager_agent.go @@ -196,9 +196,9 @@ func (c *SAgentImageCacheManager) prefetchImageCacheByUpload(ctx context.Context log.Debugf("exist: %t, remotePath: %s", exists, remotePath) if !exists || data.IsForce { if format == "iso" { - err := ds.ImportISO(ctx, localImgPath, remotePath, host) + err := ds.ImportISO(ctx, localImgPath, remotePath) if err != nil { - return nil, errors.Wrap(err, "SDatastore.ImportISO") + return nil, errors.Wrapf(err, "SDatastore.ImportISO %s -> %s", localImage, remotePath) } } else { err := ds.ImportVMDK(ctx, localImgPath, remotePath, host) diff --git a/vendor/github.com/google/uuid/.travis.yml b/vendor/github.com/google/uuid/.travis.yml deleted file mode 100644 index d8156a60ba..0000000000 --- a/vendor/github.com/google/uuid/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: go - -go: - - 1.4.3 - - 1.5.3 - - tip - -script: - - go test -v ./... diff --git a/vendor/github.com/google/uuid/CHANGELOG.md b/vendor/github.com/google/uuid/CHANGELOG.md new file mode 100644 index 0000000000..7ec5ac7ea9 --- /dev/null +++ b/vendor/github.com/google/uuid/CHANGELOG.md @@ -0,0 +1,41 @@ +# Changelog + +## [1.6.0](https://github.com/google/uuid/compare/v1.5.0...v1.6.0) (2024-01-16) + + +### Features + +* add Max UUID constant ([#149](https://github.com/google/uuid/issues/149)) ([c58770e](https://github.com/google/uuid/commit/c58770eb495f55fe2ced6284f93c5158a62e53e3)) + + +### Bug Fixes + +* fix typo in version 7 uuid documentation ([#153](https://github.com/google/uuid/issues/153)) ([016b199](https://github.com/google/uuid/commit/016b199544692f745ffc8867b914129ecb47ef06)) +* Monotonicity in UUIDv7 ([#150](https://github.com/google/uuid/issues/150)) ([a2b2b32](https://github.com/google/uuid/commit/a2b2b32373ff0b1a312b7fdf6d38a977099698a6)) + +## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12) + + +### Features + +* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29)) + +## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26) + + +### Features + +* UUIDs slice type with Strings() convenience method ([#133](https://github.com/google/uuid/issues/133)) ([cd5fbbd](https://github.com/google/uuid/commit/cd5fbbdd02f3e3467ac18940e07e062be1f864b4)) + +### Fixes + +* Clarify that Parse's job is to parse but not necessarily validate strings. (Documents current behavior) + +## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18) + + +### Bug Fixes + +* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0)) + +## Changelog diff --git a/vendor/github.com/google/uuid/CONTRIBUTING.md b/vendor/github.com/google/uuid/CONTRIBUTING.md index 04fdf09f13..a502fdc515 100644 --- a/vendor/github.com/google/uuid/CONTRIBUTING.md +++ b/vendor/github.com/google/uuid/CONTRIBUTING.md @@ -2,6 +2,22 @@ We definitely welcome patches and contribution to this project! +### Tips + +Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org). + +Always try to include a test case! If it is not possible or not necessary, +please explain why in the pull request description. + +### Releasing + +Commits that would precipitate a SemVer change, as described in the Conventional +Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action) +to create a release candidate pull request. Once submitted, `release-please` +will create a release. + +For tips on how to work with `release-please`, see its documentation. + ### Legal requirements In order to protect both you and ourselves, you will need to sign the diff --git a/vendor/github.com/google/uuid/README.md b/vendor/github.com/google/uuid/README.md index f765a46f91..3e9a61889d 100644 --- a/vendor/github.com/google/uuid/README.md +++ b/vendor/github.com/google/uuid/README.md @@ -1,6 +1,6 @@ -# uuid ![build status](https://travis-ci.org/google/uuid.svg?branch=master) +# uuid The uuid package generates and inspects UUIDs based on -[RFC 4122](http://tools.ietf.org/html/rfc4122) +[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122) and DCE 1.1: Authentication and Security Services. This package is based on the github.com/pborman/uuid package (previously named @@ -9,10 +9,12 @@ a UUID is a 16 byte array rather than a byte slice. One loss due to this change is the ability to represent an invalid UUID (vs a NIL UUID). ###### Install -`go get github.com/google/uuid` +```sh +go get github.com/google/uuid +``` ###### Documentation -[![GoDoc](https://godoc.org/github.com/google/uuid?status.svg)](http://godoc.org/github.com/google/uuid) +[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid) Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here: diff --git a/vendor/github.com/google/uuid/hash.go b/vendor/github.com/google/uuid/hash.go index b404f4bec2..dc60082d3b 100644 --- a/vendor/github.com/google/uuid/hash.go +++ b/vendor/github.com/google/uuid/hash.go @@ -17,6 +17,12 @@ var ( NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")) NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")) Nil UUID // empty UUID, all zeros + + // The Max UUID is special form of UUID that is specified to have all 128 bits set to 1. + Max = UUID{ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + } ) // NewHash returns a new UUID derived from the hash of space concatenated with diff --git a/vendor/github.com/google/uuid/node_js.go b/vendor/github.com/google/uuid/node_js.go index 24b78edc90..b2a0bc8711 100644 --- a/vendor/github.com/google/uuid/node_js.go +++ b/vendor/github.com/google/uuid/node_js.go @@ -7,6 +7,6 @@ package uuid // getHardwareInterface returns nil values for the JS version of the code. -// This remvoves the "net" dependency, because it is not used in the browser. +// This removes the "net" dependency, because it is not used in the browser. // Using the "net" library inflates the size of the transpiled JS code by 673k bytes. func getHardwareInterface(name string) (string, []byte) { return "", nil } diff --git a/vendor/github.com/google/uuid/time.go b/vendor/github.com/google/uuid/time.go index e6ef06cdc8..c351129279 100644 --- a/vendor/github.com/google/uuid/time.go +++ b/vendor/github.com/google/uuid/time.go @@ -108,12 +108,23 @@ func setClockSequence(seq int) { } // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in -// uuid. The time is only defined for version 1 and 2 UUIDs. +// uuid. The time is only defined for version 1, 2, 6 and 7 UUIDs. func (uuid UUID) Time() Time { - time := int64(binary.BigEndian.Uint32(uuid[0:4])) - time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 - time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 - return Time(time) + var t Time + switch uuid.Version() { + case 6: + time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110 + t = Time(time) + case 7: + time := binary.BigEndian.Uint64(uuid[:8]) + t = Time((time>>16)*10000 + g1582ns100) + default: // forward compatible + time := int64(binary.BigEndian.Uint32(uuid[0:4])) + time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 + time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 + t = Time(time) + } + return t } // ClockSequence returns the clock sequence encoded in uuid. diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index a57207aeb6..5232b48678 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -56,11 +56,15 @@ func IsInvalidLengthError(err error) bool { return ok } -// Parse decodes s into a UUID or returns an error. Both the standard UUID -// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and -// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the -// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex -// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. +// Parse decodes s into a UUID or returns an error if it cannot be parsed. Both +// the standard UUID forms defined in RFC 4122 +// (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) are decoded. In addition, +// Parse accepts non-standard strings such as the raw hex encoding +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx and 38 byte "Microsoft style" encodings, +// e.g. {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}. Only the middle 36 bytes are +// examined in the latter case. Parse should not be used to validate strings as +// it parses non-standard encodings as indicated above. func Parse(s string) (UUID, error) { var uuid UUID switch len(s) { @@ -69,7 +73,7 @@ func Parse(s string) (UUID, error) { // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: - if strings.ToLower(s[:9]) != "urn:uuid:" { + if !strings.EqualFold(s[:9], "urn:uuid:") { return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9]) } s = s[9:] @@ -101,7 +105,8 @@ func Parse(s string) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34} { + 24, 26, 28, 30, 32, 34, + } { v, ok := xtob(s[x], s[x+1]) if !ok { return uuid, errors.New("invalid UUID format") @@ -117,7 +122,7 @@ func ParseBytes(b []byte) (UUID, error) { switch len(b) { case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx - if !bytes.Equal(bytes.ToLower(b[:9]), []byte("urn:uuid:")) { + if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) { return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9]) } b = b[9:] @@ -145,7 +150,8 @@ func ParseBytes(b []byte) (UUID, error) { 9, 11, 14, 16, 19, 21, - 24, 26, 28, 30, 32, 34} { + 24, 26, 28, 30, 32, 34, + } { v, ok := xtob(b[x], b[x+1]) if !ok { return uuid, errors.New("invalid UUID format") @@ -180,6 +186,59 @@ func Must(uuid UUID, err error) UUID { return uuid } +// Validate returns an error if s is not a properly formatted UUID in one of the following formats: +// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} +// It returns an error if the format is invalid, otherwise nil. +func Validate(s string) error { + switch len(s) { + // Standard UUID format + case 36: + + // UUID with "urn:uuid:" prefix + case 36 + 9: + if !strings.EqualFold(s[:9], "urn:uuid:") { + return fmt.Errorf("invalid urn prefix: %q", s[:9]) + } + s = s[9:] + + // UUID enclosed in braces + case 36 + 2: + if s[0] != '{' || s[len(s)-1] != '}' { + return fmt.Errorf("invalid bracketed UUID format") + } + s = s[1 : len(s)-1] + + // UUID without hyphens + case 32: + for i := 0; i < len(s); i += 2 { + _, ok := xtob(s[i], s[i+1]) + if !ok { + return errors.New("invalid UUID format") + } + } + + default: + return invalidLengthError{len(s)} + } + + // Check for standard UUID format + if len(s) == 36 { + if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { + return errors.New("invalid UUID format") + } + for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} { + if _, ok := xtob(s[x], s[x+1]); !ok { + return errors.New("invalid UUID format") + } + } + } + + return nil +} + // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // , or "" if uuid is invalid. func (uuid UUID) String() string { @@ -292,3 +351,15 @@ func DisableRandPool() { poolMu.Lock() poolPos = randPoolSize } + +// UUIDs is a slice of UUID types. +type UUIDs []UUID + +// Strings returns a string slice containing the string form of each UUID in uuids. +func (uuids UUIDs) Strings() []string { + var uuidStrs = make([]string, len(uuids)) + for i, uuid := range uuids { + uuidStrs[i] = uuid.String() + } + return uuidStrs +} diff --git a/vendor/github.com/google/uuid/version6.go b/vendor/github.com/google/uuid/version6.go new file mode 100644 index 0000000000..339a959a7a --- /dev/null +++ b/vendor/github.com/google/uuid/version6.go @@ -0,0 +1,56 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import "encoding/binary" + +// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality. +// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs. +// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6 +// +// NewV6 returns a Version 6 UUID based on the current NodeID and clock +// sequence, and the current time. If the NodeID has not been set by SetNodeID +// or SetNodeInterface then it will be set automatically. If the NodeID cannot +// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by +// SetClockSequence then it will be set automatically. If GetTime fails to +// return the current NewV6 returns Nil and an error. +func NewV6() (UUID, error) { + var uuid UUID + now, seq, err := GetTime() + if err != nil { + return uuid, err + } + + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_high | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | time_mid | time_low_and_version | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |clk_seq_hi_res | clk_seq_low | node (0-1) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | node (2-5) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + + binary.BigEndian.PutUint64(uuid[0:], uint64(now)) + binary.BigEndian.PutUint16(uuid[8:], seq) + + uuid[6] = 0x60 | (uuid[6] & 0x0F) + uuid[8] = 0x80 | (uuid[8] & 0x3F) + + nodeMu.Lock() + if nodeID == zeroID { + setNodeInterface("") + } + copy(uuid[10:], nodeID[:]) + nodeMu.Unlock() + + return uuid, nil +} diff --git a/vendor/github.com/google/uuid/version7.go b/vendor/github.com/google/uuid/version7.go new file mode 100644 index 0000000000..3167b643d4 --- /dev/null +++ b/vendor/github.com/google/uuid/version7.go @@ -0,0 +1,104 @@ +// Copyright 2023 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "io" +) + +// UUID version 7 features a time-ordered value field derived from the widely +// implemented and well known Unix Epoch timestamp source, +// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded. +// As well as improved entropy characteristics over versions 1 or 6. +// +// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7 +// +// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible. +// +// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch). +// Uses the randomness pool if it was enabled with EnableRandPool. +// On error, NewV7 returns Nil and an error +func NewV7() (UUID, error) { + uuid, err := NewRandom() + if err != nil { + return uuid, err + } + makeV7(uuid[:]) + return uuid, nil +} + +// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch). +// it use NewRandomFromReader fill random bits. +// On error, NewV7FromReader returns Nil and an error. +func NewV7FromReader(r io.Reader) (UUID, error) { + uuid, err := NewRandomFromReader(r) + if err != nil { + return uuid, err + } + + makeV7(uuid[:]) + return uuid, nil +} + +// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6]) +// uuid[8] already has the right version number (Variant is 10) +// see function NewV7 and NewV7FromReader +func makeV7(uuid []byte) { + /* + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | unix_ts_ms | ver | rand_a (12 bit seq) | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |var| rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | rand_b | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + _ = uuid[15] // bounds check + + t, s := getV7Time() + + uuid[0] = byte(t >> 40) + uuid[1] = byte(t >> 32) + uuid[2] = byte(t >> 24) + uuid[3] = byte(t >> 16) + uuid[4] = byte(t >> 8) + uuid[5] = byte(t) + + uuid[6] = 0x70 | (0x0F & byte(s>>8)) + uuid[7] = byte(s) +} + +// lastV7time is the last time we returned stored as: +// +// 52 bits of time in milliseconds since epoch +// 12 bits of (fractional nanoseconds) >> 8 +var lastV7time int64 + +const nanoPerMilli = 1000000 + +// getV7Time returns the time in milliseconds and nanoseconds / 256. +// The returned (milli << 12 + seq) is guarenteed to be greater than +// (milli << 12 + seq) returned by any previous call to getV7Time. +func getV7Time() (milli, seq int64) { + timeMu.Lock() + defer timeMu.Unlock() + + nano := timeNow().UnixNano() + milli = nano / nanoPerMilli + // Sequence number is between 0 and 3906 (nanoPerMilli>>8) + seq = (nano - milli*nanoPerMilli) >> 8 + now := milli<<12 + seq + if now <= lastV7time { + now = lastV7time + 1 + milli = now >> 12 + seq = now & 0xfff + } + lastV7time = now + return milli, seq +} diff --git a/vendor/github.com/stretchr/objx/README.md b/vendor/github.com/stretchr/objx/README.md index 246660b21a..78dc1f8b03 100644 --- a/vendor/github.com/stretchr/objx/README.md +++ b/vendor/github.com/stretchr/objx/README.md @@ -4,20 +4,20 @@ [![Maintainability](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/maintainability)](https://codeclimate.com/github/stretchr/objx/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/1d64bc6c8474c2074f2b/test_coverage)](https://codeclimate.com/github/stretchr/objx/test_coverage) [![Sourcegraph](https://sourcegraph.com/github.com/stretchr/objx/-/badge.svg)](https://sourcegraph.com/github.com/stretchr/objx) -[![GoDoc](https://godoc.org/github.com/stretchr/objx?status.svg)](https://godoc.org/github.com/stretchr/objx) +[![GoDoc](https://pkg.go.dev/badge/github.com/stretchr/objx?utm_source=godoc)](https://pkg.go.dev/github.com/stretchr/objx) Objx - Go package for dealing with maps, slices, JSON and other data. Get started: - Install Objx with [one line of code](#installation), or [update it with another](#staying-up-to-date) -- Check out the API Documentation http://godoc.org/github.com/stretchr/objx +- Check out the API Documentation http://pkg.go.dev/github.com/stretchr/objx ## Overview Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. ### Pattern -Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: +Objx uses a predictable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: m, err := objx.FromJSON(json) @@ -74,7 +74,7 @@ To update Objx to the latest version, run: go get -u github.com/stretchr/objx ### Supported go versions -We support the lastest three major Go versions, which are 1.10, 1.11 and 1.12 at the moment. +We currently support the three recent major Go versions. ## Contributing Please feel free to submit issues, fork the repository and send pull requests! diff --git a/vendor/github.com/stretchr/objx/Taskfile.yml b/vendor/github.com/stretchr/objx/Taskfile.yml index 7746f516da..8a79e8d674 100644 --- a/vendor/github.com/stretchr/objx/Taskfile.yml +++ b/vendor/github.com/stretchr/objx/Taskfile.yml @@ -1,7 +1,4 @@ -version: '2' - -env: - GOFLAGS: -mod=vendor +version: '3' tasks: default: diff --git a/vendor/github.com/stretchr/objx/accessors.go b/vendor/github.com/stretchr/objx/accessors.go index 4c60455886..72f1d1c1ce 100644 --- a/vendor/github.com/stretchr/objx/accessors.go +++ b/vendor/github.com/stretchr/objx/accessors.go @@ -14,17 +14,17 @@ const ( // For example, `location.address.city` PathSeparator string = "." - // arrayAccesRegexString is the regex used to extract the array number + // arrayAccessRegexString is the regex used to extract the array number // from the access path - arrayAccesRegexString = `^(.+)\[([0-9]+)\]$` + arrayAccessRegexString = `^(.+)\[([0-9]+)\]$` // mapAccessRegexString is the regex used to extract the map key // from the access path mapAccessRegexString = `^([^\[]*)\[([^\]]+)\](.*)$` ) -// arrayAccesRegex is the compiled arrayAccesRegexString -var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString) +// arrayAccessRegex is the compiled arrayAccessRegexString +var arrayAccessRegex = regexp.MustCompile(arrayAccessRegexString) // mapAccessRegex is the compiled mapAccessRegexString var mapAccessRegex = regexp.MustCompile(mapAccessRegexString) @@ -37,11 +37,11 @@ var mapAccessRegex = regexp.MustCompile(mapAccessRegexString) // // Get can only operate directly on map[string]interface{} and []interface. // -// Example +// # Example // // To access the title of the third chapter of the second book, do: // -// o.Get("books[1].chapters[2].title") +// o.Get("books[1].chapters[2].title") func (m Map) Get(selector string) *Value { rawObj := access(m, selector, nil, false) return &Value{data: rawObj} @@ -52,26 +52,26 @@ func (m Map) Get(selector string) *Value { // // Set can only operate directly on map[string]interface{} and []interface // -// Example +// # Example // // To set the title of the third chapter of the second book, do: // -// o.Set("books[1].chapters[2].title","Time to Go") +// o.Set("books[1].chapters[2].title","Time to Go") func (m Map) Set(selector string, value interface{}) Map { access(m, selector, value, true) return m } -// getIndex returns the index, which is hold in s by two braches. -// It also returns s withour the index part, e.g. name[1] will return (1, name). +// getIndex returns the index, which is hold in s by two branches. +// It also returns s without the index part, e.g. name[1] will return (1, name). // If no index is found, -1 is returned func getIndex(s string) (int, string) { - arrayMatches := arrayAccesRegex.FindStringSubmatch(s) + arrayMatches := arrayAccessRegex.FindStringSubmatch(s) if len(arrayMatches) > 0 { // Get the key into the map selector := arrayMatches[1] // Get the index into the array at the key - // We know this cannt fail because arrayMatches[2] is an int for sure + // We know this can't fail because arrayMatches[2] is an int for sure index, _ := strconv.Atoi(arrayMatches[2]) return index, selector } diff --git a/vendor/github.com/stretchr/objx/conversions.go b/vendor/github.com/stretchr/objx/conversions.go index 080aa46e47..01c63d7d3b 100644 --- a/vendor/github.com/stretchr/objx/conversions.go +++ b/vendor/github.com/stretchr/objx/conversions.go @@ -15,7 +15,7 @@ import ( const SignatureSeparator = "_" // URLValuesSliceKeySuffix is the character that is used to -// specify a suffic for slices parsed by URLValues. +// specify a suffix for slices parsed by URLValues. // If the suffix is set to "[i]", then the index of the slice // is used in place of i // Ex: Suffix "[]" would have the form a[]=b&a[]=c @@ -30,7 +30,7 @@ const ( ) // SetURLValuesSliceKeySuffix sets the character that is used to -// specify a suffic for slices parsed by URLValues. +// specify a suffix for slices parsed by URLValues. // If the suffix is set to "[i]", then the index of the slice // is used in place of i // Ex: Suffix "[]" would have the form a[]=b&a[]=c diff --git a/vendor/github.com/stretchr/objx/doc.go b/vendor/github.com/stretchr/objx/doc.go index 6d6af1a83a..b170af74b3 100644 --- a/vendor/github.com/stretchr/objx/doc.go +++ b/vendor/github.com/stretchr/objx/doc.go @@ -1,19 +1,19 @@ /* -Objx - Go package for dealing with maps, slices, JSON and other data. +Package objx provides utilities for dealing with maps, slices, JSON and other data. -Overview +# Overview Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes a powerful `Get` method (among others) that allows you to easily and quickly get access to data within the map, without having to worry too much about type assertions, missing data, default values etc. -Pattern +# Pattern -Objx uses a preditable pattern to make access data from within `map[string]interface{}` easy. +Objx uses a predictable pattern to make access data from within `map[string]interface{}` easy. Call one of the `objx.` functions to create your `objx.Map` to get going: - m, err := objx.FromJSON(json) + m, err := objx.FromJSON(json) NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, the rest will be optimistic and try to figure things out without panicking. @@ -21,46 +21,46 @@ the rest will be optimistic and try to figure things out without panicking. Use `Get` to access the value you're interested in. You can use dot and array notation too: - m.Get("places[0].latlng") + m.Get("places[0].latlng") Once you have sought the `Value` you're interested in, you can use the `Is*` methods to determine its type. - if m.Get("code").IsStr() { // Your code... } + if m.Get("code").IsStr() { // Your code... } Or you can just assume the type, and use one of the strong type methods to extract the real value: - m.Get("code").Int() + m.Get("code").Int() If there's no value there (or if it's the wrong type) then a default value will be returned, or you can be explicit about the default value. - Get("code").Int(-1) + Get("code").Int(-1) If you're dealing with a slice of data as a value, Objx provides many useful methods for iterating, manipulating and selecting that data. You can find out more by exploring the index below. -Reading data +# Reading data A simple example of how to use Objx: - // Use MustFromJSON to make an objx.Map from some JSON - m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) + // Use MustFromJSON to make an objx.Map from some JSON + m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) - // Get the details - name := m.Get("name").Str() - age := m.Get("age").Int() + // Get the details + name := m.Get("name").Str() + age := m.Get("age").Int() - // Get their nickname (or use their name if they don't have one) - nickname := m.Get("nickname").Str(name) + // Get their nickname (or use their name if they don't have one) + nickname := m.Get("nickname").Str(name) -Ranging +# Ranging Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For example, to `range` the data, do what you would expect: - m := objx.MustFromJSON(json) - for key, value := range m { - // Your code... - } + m := objx.MustFromJSON(json) + for key, value := range m { + // Your code... + } */ package objx diff --git a/vendor/github.com/stretchr/objx/map.go b/vendor/github.com/stretchr/objx/map.go index a64712a08b..ab9f9ae67c 100644 --- a/vendor/github.com/stretchr/objx/map.go +++ b/vendor/github.com/stretchr/objx/map.go @@ -47,17 +47,16 @@ func New(data interface{}) Map { // // The arguments follow a key, value pattern. // -// // Returns nil if any key argument is non-string or if there are an odd number of arguments. // -// Example +// # Example // // To easily create Maps: // -// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) +// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) // -// // creates an Map equivalent to -// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}} +// // creates an Map equivalent to +// m := objx.Map{"name": "Mat", "age": 29, "subobj": objx.Map{"active": true}} func MSI(keyAndValuePairs ...interface{}) Map { newMap := Map{} keyAndValuePairsLen := len(keyAndValuePairs) diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare.go b/vendor/github.com/stretchr/testify/assert/assertion_compare.go index 95d8e59da6..4d4b4aad6f 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_compare.go @@ -28,6 +28,8 @@ var ( uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) + uintptrType = reflect.TypeOf(uintptr(1)) + float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) @@ -308,11 +310,11 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Struct: { // All structs enter here. We're not interested in most types. - if !canConvert(obj1Value, timeType) { + if !obj1Value.CanConvert(timeType) { break } - // time.Time can compared! + // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) @@ -328,7 +330,7 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { case reflect.Slice: { // We only care about the []byte type. - if !canConvert(obj1Value, bytesType) { + if !obj1Value.CanConvert(bytesType) { break } @@ -345,6 +347,26 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { return CompareType(bytes.Compare(bytesObj1, bytesObj2)), true } + case reflect.Uintptr: + { + uintptrObj1, ok := obj1.(uintptr) + if !ok { + uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) + } + uintptrObj2, ok := obj2.(uintptr) + if !ok { + uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) + } + if uintptrObj1 > uintptrObj2 { + return compareGreater, true + } + if uintptrObj1 == uintptrObj2 { + return compareEqual, true + } + if uintptrObj1 < uintptrObj2 { + return compareLess, true + } + } } return compareEqual, false @@ -352,9 +374,9 @@ func compare(obj1, obj2 interface{}, kind reflect.Kind) (CompareType, bool) { // Greater asserts that the first element is greater than the second // -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -364,10 +386,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface // GreaterOrEqual asserts that the first element is greater than or equal to the second // -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -377,9 +399,9 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in // Less asserts that the first element is less than the second // -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -389,10 +411,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) // LessOrEqual asserts that the first element is less than or equal to the second // -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -402,8 +424,8 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter // Positive asserts that the specified element is positive // -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -414,8 +436,8 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { // Negative asserts that the specified element is negative // -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go deleted file mode 100644 index da867903e2..0000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_can_convert.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build go1.17 -// +build go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_legacy.go - -package assert - -import "reflect" - -// Wrapper around reflect.Value.CanConvert, for compatibility -// reasons. -func canConvert(value reflect.Value, to reflect.Type) bool { - return value.CanConvert(to) -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go b/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go deleted file mode 100644 index 1701af2a3c..0000000000 --- a/vendor/github.com/stretchr/testify/assert/assertion_compare_legacy.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build !go1.17 -// +build !go1.17 - -// TODO: once support for Go 1.16 is dropped, this file can be -// merged/removed with assertion_compare_go1.17_test.go and -// assertion_compare_can_convert.go - -package assert - -import "reflect" - -// Older versions of Go does not have the reflect.Value.CanConvert -// method. -func canConvert(value reflect.Value, to reflect.Type) bool { - return false -} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go index 7880b8f943..3ddab109ad 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_format.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -22,9 +19,9 @@ func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bo // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -56,7 +53,7 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// assert.Emptyf(t, obj, "error message %s", "formatted") +// assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -66,7 +63,7 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) boo // Equalf asserts that two objects are equal. // -// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -81,8 +78,8 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -90,10 +87,27 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualExportedValuesf asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true +// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false +func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") +// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -103,10 +117,10 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -126,8 +140,8 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -147,7 +161,7 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -155,9 +169,34 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) } +// EventuallyWithTf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + // Exactlyf asserts that two objects are equal in value and type. // -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") +// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -183,7 +222,7 @@ func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{} // Falsef asserts that the specified value is false. // -// assert.Falsef(t, myBool, "error message %s", "formatted") +// assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -202,9 +241,9 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool // Greaterf asserts that the first element is greater than the second // -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -214,10 +253,10 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in // GreaterOrEqualf asserts that the first element is greater than or equal to the second // -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -228,7 +267,7 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { @@ -241,7 +280,7 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { @@ -253,7 +292,7 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // HTTPErrorf asserts that a specified handler returns an error status code. // -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -265,7 +304,7 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // HTTPRedirectf asserts that a specified handler returns a redirect status code. // -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -277,7 +316,7 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // HTTPStatusCodef asserts that a specified handler returns a specified status code. // -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") +// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { @@ -289,7 +328,7 @@ func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url st // HTTPSuccessf asserts that a specified handler returns a success status code. // -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -301,7 +340,7 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin // Implementsf asserts that an object is implemented by the specified interface. // -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -311,7 +350,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms // InDeltaf asserts that the two numerals are within delta of each other. // -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -353,9 +392,9 @@ func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsil // IsDecreasingf asserts that the collection is decreasing // -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -365,9 +404,9 @@ func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface // IsIncreasingf asserts that the collection is increasing // -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -377,9 +416,9 @@ func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface // IsNonDecreasingf asserts that the collection is not decreasing // -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -389,9 +428,9 @@ func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interf // IsNonIncreasingf asserts that the collection is not increasing // -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -409,7 +448,7 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin // JSONEqf asserts that two JSON strings are equivalent. // -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -420,7 +459,7 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -430,9 +469,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf // Lessf asserts that the first element is less than the second // -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") +// assert.Lessf(t, "a", "b", "error message %s", "formatted") func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -442,10 +481,10 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter // LessOrEqualf asserts that the first element is less than or equal to the second // -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -455,8 +494,8 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args . // Negativef asserts that the specified element is negative // -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -467,7 +506,7 @@ func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -477,7 +516,7 @@ func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time. // Nilf asserts that the specified object is nil. // -// assert.Nilf(t, err, "error message %s", "formatted") +// assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -496,10 +535,10 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool // NoErrorf asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -519,9 +558,9 @@ func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) boo // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -532,9 +571,9 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -544,7 +583,7 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) // NotEqualf asserts that the specified values are NOT equal. // -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -557,7 +596,7 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") +// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -574,9 +613,19 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // -// assert.NotNilf(t, err, "error message %s", "formatted") +// assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -586,7 +635,7 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bo // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -596,8 +645,8 @@ func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bo // NotRegexpf asserts that a specified regexp does not match a string. // -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -607,7 +656,7 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args .. // NotSamef asserts that two pointers do not reference the same object. // -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") +// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -618,10 +667,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -639,7 +690,7 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { // Panicsf asserts that the code inside the specified PanicTestFunc panics. // -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -651,7 +702,7 @@ func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -662,7 +713,7 @@ func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -672,8 +723,8 @@ func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg str // Positivef asserts that the specified element is positive // -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -683,8 +734,8 @@ func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool // Regexpf asserts that a specified regexp matches a string. // -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -694,7 +745,7 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in // Samef asserts that two pointers reference the same object. // -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -705,10 +756,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -718,7 +770,7 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args // Truef asserts that the specified value is true. // -// assert.Truef(t, myBool, "error message %s", "formatted") +// assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -728,7 +780,7 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { // WithinDurationf asserts that the two times are within duration delta of each other. // -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -738,7 +790,7 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim // WithinRangef asserts that a time is within a time range (inclusive). // -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") +// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go index 339515b8bf..a84e09bd40 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_forward.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package assert @@ -30,9 +27,9 @@ func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{} // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -43,9 +40,9 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -98,7 +95,7 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// a.Empty(obj) +// a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -109,7 +106,7 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// a.Emptyf(obj, "error message %s", "formatted") +// a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -119,7 +116,7 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // Equal asserts that two objects are equal. // -// a.Equal(123, 123) +// a.Equal(123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -134,8 +131,8 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -146,8 +143,8 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -155,10 +152,44 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a return EqualErrorf(a.t, theError, errString, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualExportedValues asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true +// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false +func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualExportedValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualExportedValuesf asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true +// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false +func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualExportedValuesf(a.t, expected, actual, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // -// a.EqualValues(uint32(123), int32(123)) +// a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -166,10 +197,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn return EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") +// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -179,7 +210,7 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // Equalf asserts that two objects are equal. // -// a.Equalf(123, 123, "error message %s", "formatted") +// a.Equalf(123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -193,10 +224,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -225,8 +256,8 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args .. // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -237,8 +268,8 @@ func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs . // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -266,10 +297,10 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -280,7 +311,7 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -288,10 +319,60 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) } +// EventuallyWithT asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// a.EventuallyWithT(func(c *assert.CollectT) { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// EventuallyWithTf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) +} + // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -301,7 +382,7 @@ func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, t // Exactly asserts that two objects are equal in value and type. // -// a.Exactly(int32(123), int64(123)) +// a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -311,7 +392,7 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg // Exactlyf asserts that two objects are equal in value and type. // -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") +// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -353,7 +434,7 @@ func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{ // False asserts that the specified value is false. // -// a.False(myBool) +// a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -363,7 +444,7 @@ func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { // Falsef asserts that the specified value is false. // -// a.Falsef(myBool, "error message %s", "formatted") +// a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -391,9 +472,9 @@ func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) b // Greater asserts that the first element is greater than the second // -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -403,10 +484,10 @@ func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...inter // GreaterOrEqual asserts that the first element is greater than or equal to the second // -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -416,10 +497,10 @@ func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs . // GreaterOrEqualf asserts that the first element is greater than or equal to the second // -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -429,9 +510,9 @@ func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, // Greaterf asserts that the first element is greater than the second // -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") +// a.Greaterf("b", "a", "error message %s", "formatted") func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -442,7 +523,7 @@ func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args . // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { @@ -455,7 +536,7 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { @@ -468,7 +549,7 @@ func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { @@ -481,7 +562,7 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { @@ -493,7 +574,7 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // HTTPError asserts that a specified handler returns an error status code. // -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -505,7 +586,7 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // HTTPErrorf asserts that a specified handler returns an error status code. // -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -517,7 +598,7 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // HTTPRedirect asserts that a specified handler returns a redirect status code. // -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -529,7 +610,7 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // HTTPRedirectf asserts that a specified handler returns a redirect status code. // -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -541,7 +622,7 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // HTTPStatusCode asserts that a specified handler returns a specified status code. // -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) +// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { @@ -553,7 +634,7 @@ func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url // HTTPStatusCodef asserts that a specified handler returns a specified status code. // -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") +// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { @@ -565,7 +646,7 @@ func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, ur // HTTPSuccess asserts that a specified handler returns a success status code. // -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -577,7 +658,7 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // HTTPSuccessf asserts that a specified handler returns a success status code. // -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { @@ -589,7 +670,7 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // Implements asserts that an object is implemented by the specified interface. // -// a.Implements((*MyInterface)(nil), new(MyObject)) +// a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -599,7 +680,7 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // Implementsf asserts that an object is implemented by the specified interface. // -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -609,7 +690,7 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{} // InDelta asserts that the two numerals are within delta of each other. // -// a.InDelta(math.Pi, 22/7.0, 0.01) +// a.InDelta(math.Pi, 22/7.0, 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -651,7 +732,7 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del // InDeltaf asserts that the two numerals are within delta of each other. // -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -693,9 +774,9 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo // IsDecreasing asserts that the collection is decreasing // -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -705,9 +786,9 @@ func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) // IsDecreasingf asserts that the collection is decreasing // -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -717,9 +798,9 @@ func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...inter // IsIncreasing asserts that the collection is increasing // -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -729,9 +810,9 @@ func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) // IsIncreasingf asserts that the collection is increasing // -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -741,9 +822,9 @@ func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...inter // IsNonDecreasing asserts that the collection is not decreasing // -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -753,9 +834,9 @@ func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface // IsNonDecreasingf asserts that the collection is not decreasing // -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -765,9 +846,9 @@ func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...in // IsNonIncreasing asserts that the collection is not increasing // -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -777,9 +858,9 @@ func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface // IsNonIncreasingf asserts that the collection is not increasing // -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -805,7 +886,7 @@ func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg s // JSONEq asserts that two JSON strings are equivalent. // -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -815,7 +896,7 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf // JSONEqf asserts that two JSON strings are equivalent. // -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -826,7 +907,7 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // -// a.Len(mySlice, 3) +// a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -837,7 +918,7 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // -// a.Lenf(mySlice, 3, "error message %s", "formatted") +// a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -847,9 +928,9 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in // Less asserts that the first element is less than the second // -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -859,10 +940,10 @@ func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interfac // LessOrEqual asserts that the first element is less than or equal to the second // -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -872,10 +953,10 @@ func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...i // LessOrEqualf asserts that the first element is less than or equal to the second // -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -885,9 +966,9 @@ func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, ar // Lessf asserts that the first element is less than the second // -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1), float64(2), "error message %s", "formatted") +// a.Lessf("a", "b", "error message %s", "formatted") func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -897,8 +978,8 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i // Negative asserts that the specified element is negative // -// a.Negative(-1) -// a.Negative(-1.23) +// a.Negative(-1) +// a.Negative(-1.23) func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -908,8 +989,8 @@ func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { // Negativef asserts that the specified element is negative // -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -920,7 +1001,7 @@ func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) b // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) +// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -931,7 +1012,7 @@ func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick ti // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -941,7 +1022,7 @@ func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick t // Nil asserts that the specified object is nil. // -// a.Nil(err) +// a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -951,7 +1032,7 @@ func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { // Nilf asserts that the specified object is nil. // -// a.Nilf(err, "error message %s", "formatted") +// a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -979,10 +1060,10 @@ func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) // NoError asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -992,10 +1073,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { // NoErrorf asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1024,9 +1105,9 @@ func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1037,9 +1118,9 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1050,9 +1131,9 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1063,9 +1144,9 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) boo // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1075,7 +1156,7 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // NotEqual asserts that the specified values are NOT equal. // -// a.NotEqual(obj1, obj2) +// a.NotEqual(obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1088,7 +1169,7 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // NotEqualValues asserts that two objects are not equal even when converted to the same type // -// a.NotEqualValues(obj1, obj2) +// a.NotEqualValues(obj1, obj2) func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1098,7 +1179,7 @@ func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, ms // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") +// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1108,7 +1189,7 @@ func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, m // NotEqualf asserts that the specified values are NOT equal. // -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1137,9 +1218,29 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in return NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // -// a.NotNil(err) +// a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1149,7 +1250,7 @@ func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool // NotNilf asserts that the specified object is not nil. // -// a.NotNilf(err, "error message %s", "formatted") +// a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1159,7 +1260,7 @@ func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{} // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // -// a.NotPanics(func(){ RemainCalm() }) +// a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1169,7 +1270,7 @@ func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1179,8 +1280,8 @@ func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{} // NotRegexp asserts that a specified regexp does not match a string. // -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1190,8 +1291,8 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // NotRegexpf asserts that a specified regexp does not match a string. // -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1201,7 +1302,7 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // NotSame asserts that two pointers do not reference the same object. // -// a.NotSame(ptr1, ptr2) +// a.NotSame(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1214,7 +1315,7 @@ func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArg // NotSamef asserts that two pointers do not reference the same object. // -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") +// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1225,10 +1326,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri return NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1236,10 +1339,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs return NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1265,7 +1370,7 @@ func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bo // Panics asserts that the code inside the specified PanicTestFunc panics. // -// a.Panics(func(){ GoCrazy() }) +// a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1277,7 +1382,7 @@ func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) +// a.PanicsWithError("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1289,7 +1394,7 @@ func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndAr // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1300,7 +1405,7 @@ func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg str // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1311,7 +1416,7 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgA // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1321,7 +1426,7 @@ func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg // Panicsf asserts that the code inside the specified PanicTestFunc panics. // -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1331,8 +1436,8 @@ func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) b // Positive asserts that the specified element is positive // -// a.Positive(1) -// a.Positive(1.23) +// a.Positive(1) +// a.Positive(1.23) func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1342,8 +1447,8 @@ func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { // Positivef asserts that the specified element is positive // -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1353,8 +1458,8 @@ func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) b // Regexp asserts that a specified regexp matches a string. // -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1364,8 +1469,8 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // Regexpf asserts that a specified regexp matches a string. // -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1375,7 +1480,7 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // Same asserts that two pointers reference the same object. // -// a.Same(ptr1, ptr2) +// a.Same(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1388,7 +1493,7 @@ func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs . // Samef asserts that two pointers reference the same object. // -// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// a.Samef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1399,10 +1504,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, return Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1410,10 +1516,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... return Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1423,7 +1530,7 @@ func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, a // True asserts that the specified value is true. // -// a.True(myBool) +// a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1433,7 +1540,7 @@ func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { // Truef asserts that the specified value is true. // -// a.Truef(myBool, "error message %s", "formatted") +// a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1443,7 +1550,7 @@ func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { // WithinDuration asserts that the two times are within duration delta of each other. // -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1453,7 +1560,7 @@ func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta // WithinDurationf asserts that the two times are within duration delta of each other. // -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1463,7 +1570,7 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta // WithinRange asserts that a time is within a time range (inclusive). // -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) +// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1473,7 +1580,7 @@ func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Tim // WithinRangef asserts that a time is within a time range (inclusive). // -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") +// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go index 7594487835..00df62a059 100644 --- a/vendor/github.com/stretchr/testify/assert/assertion_order.go +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -46,36 +46,36 @@ func isOrdered(t TestingT, object interface{}, allowedComparesResults []CompareT // IsIncreasing asserts that the collection is increasing // -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []CompareType{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // IsNonIncreasing asserts that the collection is not increasing // -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []CompareType{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // IsDecreasing asserts that the collection is decreasing // -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []CompareType{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // IsNonDecreasing asserts that the collection is not decreasing // -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []CompareType{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) } diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index fa1245b189..0b7570f21c 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -8,7 +8,6 @@ import ( "fmt" "math" "os" - "path/filepath" "reflect" "regexp" "runtime" @@ -20,7 +19,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" - yaml "gopkg.in/yaml.v3" + "gopkg.in/yaml.v3" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" @@ -76,6 +75,84 @@ func ObjectsAreEqual(expected, actual interface{}) bool { return bytes.Equal(exp, act) } +// copyExportedFields iterates downward through nested data structures and creates a copy +// that only contains the exported struct fields. +func copyExportedFields(expected interface{}) interface{} { + if isNil(expected) { + return expected + } + + expectedType := reflect.TypeOf(expected) + expectedKind := expectedType.Kind() + expectedValue := reflect.ValueOf(expected) + + switch expectedKind { + case reflect.Struct: + result := reflect.New(expectedType).Elem() + for i := 0; i < expectedType.NumField(); i++ { + field := expectedType.Field(i) + isExported := field.IsExported() + if isExported { + fieldValue := expectedValue.Field(i) + if isNil(fieldValue) || isNil(fieldValue.Interface()) { + continue + } + newValue := copyExportedFields(fieldValue.Interface()) + result.Field(i).Set(reflect.ValueOf(newValue)) + } + } + return result.Interface() + + case reflect.Ptr: + result := reflect.New(expectedType.Elem()) + unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) + result.Elem().Set(reflect.ValueOf(unexportedRemoved)) + return result.Interface() + + case reflect.Array, reflect.Slice: + var result reflect.Value + if expectedKind == reflect.Array { + result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() + } else { + result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) + } + for i := 0; i < expectedValue.Len(); i++ { + index := expectedValue.Index(i) + if isNil(index) { + continue + } + unexportedRemoved := copyExportedFields(index.Interface()) + result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) + } + return result.Interface() + + case reflect.Map: + result := reflect.MakeMap(expectedType) + for _, k := range expectedValue.MapKeys() { + index := expectedValue.MapIndex(k) + unexportedRemoved := copyExportedFields(index.Interface()) + result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) + } + return result.Interface() + + default: + return expected + } +} + +// ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are +// considered equal. This comparison of only exported fields is applied recursively to nested data +// structures. +// +// This function does no assertion of any kind. +// +// Deprecated: Use [EqualExportedValues] instead. +func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { + expectedCleaned := copyExportedFields(expected) + actualCleaned := copyExportedFields(actual) + return ObjectsAreEqualValues(expectedCleaned, actualCleaned) +} + // ObjectsAreEqualValues gets whether two objects are equal, or if their // values are equal. func ObjectsAreEqualValues(expected, actual interface{}) bool { @@ -83,17 +160,40 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool { return true } - actualType := reflect.TypeOf(actual) - if actualType == nil { + expectedValue := reflect.ValueOf(expected) + actualValue := reflect.ValueOf(actual) + if !expectedValue.IsValid() || !actualValue.IsValid() { return false } - expectedValue := reflect.ValueOf(expected) - if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { - // Attempt comparison after type conversion - return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + + expectedType := expectedValue.Type() + actualType := actualValue.Type() + if !expectedType.ConvertibleTo(actualType) { + return false } - return false + if !isNumericType(expectedType) || !isNumericType(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual( + expectedValue.Convert(actualType).Interface(), actual, + ) + } + + // If BOTH values are numeric, there are chances of false positives due + // to overflow or underflow. So, we need to make sure to always convert + // the smaller type to a larger type before comparing. + if expectedType.Size() >= actualType.Size() { + return actualValue.Convert(expectedType).Interface() == expected + } + + return expectedValue.Convert(actualType).Interface() == actual +} + +// isNumericType returns true if the type is one of: +// int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, +// float32, float64, complex64, complex128 +func isNumericType(t reflect.Type) bool { + return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object @@ -141,12 +241,11 @@ func CallerInfo() []string { } parts := strings.Split(file, "/") - file = parts[len(parts)-1] if len(parts) > 1 { + filename := parts[len(parts)-1] dir := parts[len(parts)-2] - if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { - path, _ := filepath.Abs(file) - callers = append(callers, fmt.Sprintf("%s:%d", path, line)) + if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) } } @@ -197,7 +296,7 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). -// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) @@ -273,7 +372,7 @@ type labeledContent struct { // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: // -// \t{{label}}:{{align_spaces}}\t{{content}}\n +// \t{{label}}:{{align_spaces}}\t{{content}}\n // // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this @@ -296,7 +395,7 @@ func labeledOutput(content ...labeledContent) string { // Implements asserts that an object is implemented by the specified interface. // -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -313,6 +412,25 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg return true } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) + } + if reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) + } + + return true +} + // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { @@ -328,7 +446,7 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs // Equal asserts that two objects are equal. // -// assert.Equal(t, 123, 123) +// assert.Equal(t, 123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -369,7 +487,7 @@ func validateEqualArgs(expected, actual interface{}) error { // Same asserts that two pointers reference the same object. // -// assert.Same(t, ptr1, ptr2) +// assert.Same(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -389,7 +507,7 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b // NotSame asserts that two pointers do not reference the same object. // -// assert.NotSame(t, ptr1, ptr2) +// assert.NotSame(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -427,7 +545,7 @@ func samePointers(first, second interface{}) bool { // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed -// with the type name, and the value will be enclosed in parenthesis similar +// with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { @@ -454,10 +572,10 @@ func truncatingFormat(data interface{}) string { return value } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // -// assert.EqualValues(t, uint32(123), int32(123)) +// assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -475,9 +593,60 @@ func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interfa } +// EqualExportedValues asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true +// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false +func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) + } + + if aType.Kind() == reflect.Ptr { + aType = aType.Elem() + } + if bType.Kind() == reflect.Ptr { + bType = bType.Elem() + } + + if aType.Kind() != reflect.Struct { + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) + } + + if bType.Kind() != reflect.Struct { + return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) + } + + expected = copyExportedFields(expected) + actual = copyExportedFields(actual) + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true +} + // Exactly asserts that two objects are equal in value and type. // -// assert.Exactly(t, int32(123), int64(123)) +// assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -496,7 +665,7 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{} // NotNil asserts that the specified object is not nil. // -// assert.NotNil(t, err) +// assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if !isNil(object) { return true @@ -507,17 +676,6 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } -// containsKind checks if a specified kind in the slice of kinds. -func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { - for i := 0; i < len(kinds); i++ { - if kind == kinds[i] { - return true - } - } - - return false -} - // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -525,16 +683,13 @@ func isNil(object interface{}) bool { } value := reflect.ValueOf(object) - kind := value.Kind() - isNilableKind := containsKind( - []reflect.Kind{ - reflect.Chan, reflect.Func, - reflect.Interface, reflect.Map, - reflect.Ptr, reflect.Slice}, - kind) + switch value.Kind() { + case + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice, reflect.UnsafePointer: - if isNilableKind && value.IsNil() { - return true + return value.IsNil() } return false @@ -542,7 +697,7 @@ func isNil(object interface{}) bool { // Nil asserts that the specified object is nil. // -// assert.Nil(t, err) +// assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if isNil(object) { return true @@ -585,7 +740,7 @@ func isEmpty(object interface{}) bool { // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// assert.Empty(t, obj) +// assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := isEmpty(object) if !pass { @@ -602,9 +757,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := !isEmpty(object) if !pass { @@ -618,40 +773,38 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { } -// getLen try to get length of object. -// return (false, 0) if impossible. -func getLen(x interface{}) (ok bool, length int) { +// getLen tries to get the length of an object. +// It returns (0, false) if impossible. +func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { - if e := recover(); e != nil { - ok = false - } + ok = recover() == nil }() - return true, v.Len() + return v.Len(), true } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // -// assert.Len(t, mySlice, 3) +// assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } - ok, l := getLen(object) + l, ok := getLen(object) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { - return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } // True asserts that the specified value is true. // -// assert.True(t, myBool) +// assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { if !value { if h, ok := t.(tHelper); ok { @@ -666,7 +819,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { // False asserts that the specified value is false. // -// assert.False(t, myBool) +// assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value { if h, ok := t.(tHelper); ok { @@ -681,7 +834,7 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { // NotEqual asserts that the specified values are NOT equal. // -// assert.NotEqual(t, obj1, obj2) +// assert.NotEqual(t, obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -704,7 +857,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{ // NotEqualValues asserts that two objects are not equal even when converted to the same type // -// assert.NotEqualValues(t, obj1, obj2) +// assert.NotEqualValues(t, obj1, obj2) func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -763,9 +916,9 @@ func containsElement(list interface{}, element interface{}) (ok, found bool) { // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -786,9 +939,9 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -796,20 +949,21 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) ok, found := containsElement(s, contains) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) } if found { - return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...) } return true } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -818,59 +972,56 @@ func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok return true // we consider nil to be equal to the nil set } - defer func() { - if e := recover(); e != nil { - ok = false - } - }() - listKind := reflect.TypeOf(list).Kind() - subsetKind := reflect.TypeOf(subset).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } + subsetKind := reflect.TypeOf(subset).Kind() if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } - subsetValue := reflect.ValueOf(subset) if subsetKind == reflect.Map && listKind == reflect.Map { - listValue := reflect.ValueOf(list) - subsetKeys := subsetValue.MapKeys() + subsetMap := reflect.ValueOf(subset) + actualMap := reflect.ValueOf(list) - for i := 0; i < len(subsetKeys); i++ { - subsetKey := subsetKeys[i] - subsetElement := subsetValue.MapIndex(subsetKey).Interface() - listElement := listValue.MapIndex(subsetKey).Interface() + for _, k := range subsetMap.MapKeys() { + ev := subsetMap.MapIndex(k) + av := actualMap.MapIndex(k) - if !ObjectsAreEqual(subsetElement, listElement) { - return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, subsetElement), msgAndArgs...) + if !av.IsValid() { + return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) + } + if !ObjectsAreEqual(ev.Interface(), av.Interface()) { + return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) } } return true } - for i := 0; i < subsetValue.Len(); i++ { - element := subsetValue.Index(i).Interface() + subsetList := reflect.ValueOf(subset) + for i := 0; i < subsetList.Len(); i++ { + element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) if !ok { - return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) } if !found { - return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) + return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) } } return true } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() @@ -879,34 +1030,28 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) } - defer func() { - if e := recover(); e != nil { - ok = false - } - }() - listKind := reflect.TypeOf(list).Kind() - subsetKind := reflect.TypeOf(subset).Kind() - if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } + subsetKind := reflect.TypeOf(subset).Kind() if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } - subsetValue := reflect.ValueOf(subset) if subsetKind == reflect.Map && listKind == reflect.Map { - listValue := reflect.ValueOf(list) - subsetKeys := subsetValue.MapKeys() + subsetMap := reflect.ValueOf(subset) + actualMap := reflect.ValueOf(list) - for i := 0; i < len(subsetKeys); i++ { - subsetKey := subsetKeys[i] - subsetElement := subsetValue.MapIndex(subsetKey).Interface() - listElement := listValue.MapIndex(subsetKey).Interface() + for _, k := range subsetMap.MapKeys() { + ev := subsetMap.MapIndex(k) + av := actualMap.MapIndex(k) - if !ObjectsAreEqual(subsetElement, listElement) { + if !av.IsValid() { + return true + } + if !ObjectsAreEqual(ev.Interface(), av.Interface()) { return true } } @@ -914,8 +1059,9 @@ func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) } - for i := 0; i < subsetValue.Len(); i++ { - element := subsetValue.Index(i).Interface() + subsetList := reflect.ValueOf(subset) + for i := 0; i < subsetList.Len(); i++ { + element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) @@ -1060,7 +1206,7 @@ func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string // Panics asserts that the code inside the specified PanicTestFunc panics. // -// assert.Panics(t, func(){ GoCrazy() }) +// assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1076,7 +1222,7 @@ func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1097,7 +1243,7 @@ func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndAr // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) +// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1117,7 +1263,7 @@ func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs . // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // -// assert.NotPanics(t, func(){ RemainCalm() }) +// assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1132,7 +1278,7 @@ func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { // WithinDuration asserts that the two times are within duration delta of each other. // -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1148,7 +1294,7 @@ func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, // WithinRange asserts that a time is within a time range (inclusive). // -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) +// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1207,7 +1353,7 @@ func toFloat(x interface{}) (float64, bool) { // InDelta asserts that the two numerals are within delta of each other. // -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) +// assert.InDelta(t, math.Pi, 22/7.0, 0.01) func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1336,7 +1482,7 @@ func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAnd h.Helper() } if math.IsNaN(epsilon) { - return Fail(t, "epsilon must not be NaN") + return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { @@ -1355,19 +1501,26 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m if h, ok := t.(tHelper); ok { h.Helper() } - if expected == nil || actual == nil || - reflect.TypeOf(actual).Kind() != reflect.Slice || - reflect.TypeOf(expected).Kind() != reflect.Slice { + + if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } - actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) + actualSlice := reflect.ValueOf(actual) - for i := 0; i < actualSlice.Len(); i++ { - result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) - if !result { - return result + if expectedSlice.Type().Kind() != reflect.Slice { + return Fail(t, "Expected value must be slice", msgAndArgs...) + } + + expectedLen := expectedSlice.Len() + if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { + return false + } + + for i := 0; i < expectedLen; i++ { + if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { + return false } } @@ -1380,10 +1533,10 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, m // NoError asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { if err != nil { if h, ok := t.(tHelper); ok { @@ -1397,10 +1550,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { if err == nil { if h, ok := t.(tHelper); ok { @@ -1415,8 +1568,8 @@ func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1438,8 +1591,8 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1472,8 +1625,8 @@ func matchRegexp(rx interface{}, str interface{}) bool { // Regexp asserts that a specified regexp matches a string. // -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1490,8 +1643,8 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface // NotRegexp asserts that a specified regexp does not match a string. // -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1603,7 +1756,7 @@ func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { // JSONEq asserts that two JSON strings are equivalent. // -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1726,7 +1879,7 @@ type tHelper interface { // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() @@ -1756,10 +1909,94 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t } } +// CollectT implements the TestingT interface and collects all errors. +type CollectT struct { + errors []error +} + +// Errorf collects the error. +func (c *CollectT) Errorf(format string, args ...interface{}) { + c.errors = append(c.errors, fmt.Errorf(format, args...)) +} + +// FailNow panics. +func (*CollectT) FailNow() { + panic("Assertion failed") +} + +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Reset() { + panic("Reset() is deprecated") +} + +// Deprecated: That was a method for internal usage that should not have been published. Now just panics. +func (*CollectT) Copy(TestingT) { + panic("Copy() is deprecated") +} + +// EventuallyWithT asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// assert.EventuallyWithT(t, func(c *assert.CollectT) { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + var lastFinishedTickErrs []error + ch := make(chan []error, 1) + + timer := time.NewTimer(waitFor) + defer timer.Stop() + + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for tick := ticker.C; ; { + select { + case <-timer.C: + for _, err := range lastFinishedTickErrs { + t.Errorf("%v", err) + } + return Fail(t, "Condition never satisfied", msgAndArgs...) + case <-tick: + tick = nil + go func() { + collect := new(CollectT) + defer func() { + ch <- collect.errors + }() + condition(collect) + }() + case errs := <-ch: + if len(errs) == 0 { + return true + } + // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. + lastFinishedTickErrs = errs + tick = ticker.C + } + } +} + // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) +// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go index c9dccc4d6c..4953981d38 100644 --- a/vendor/github.com/stretchr/testify/assert/doc.go +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -1,39 +1,40 @@ // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // -// Example Usage +// # Example Usage // // The following is a complete example using assert in a standard test function: -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) // -// func TestSomething(t *testing.T) { +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) // -// var a string = "Hello" -// var b string = "Hello" +// func TestSomething(t *testing.T) { // -// assert.Equal(t, a, b, "The two words should be the same.") +// var a string = "Hello" +// var b string = "Hello" // -// } +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } // // if you assert many times, use the format below: // -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// ) +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) // -// func TestSomething(t *testing.T) { -// assert := assert.New(t) +// func TestSomething(t *testing.T) { +// assert := assert.New(t) // -// var a string = "Hello" -// var b string = "Hello" +// var a string = "Hello" +// var b string = "Hello" // -// assert.Equal(a, b, "The two words should be the same.") -// } +// assert.Equal(a, b, "The two words should be the same.") +// } // -// Assertions +// # Assertions // // Assertions allow you to easily write test code, and are global funcs in the `assert` package. // All assertion functions take, as the first argument, the `*testing.T` object provided by the diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go index 4ed341dd28..861ed4b7ce 100644 --- a/vendor/github.com/stretchr/testify/assert/http_assertions.go +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -12,7 +12,7 @@ import ( // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url, nil) + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } @@ -23,7 +23,7 @@ func httpCode(handler http.HandlerFunc, method, url string, values url.Values) ( // HTTPSuccess asserts that a specified handler returns a success status code. // -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -32,12 +32,12 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { - Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode @@ -45,7 +45,7 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, value // HTTPRedirect asserts that a specified handler returns a redirect status code. // -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -54,12 +54,12 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { - Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode @@ -67,7 +67,7 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, valu // HTTPError asserts that a specified handler returns an error status code. // -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { @@ -76,12 +76,12 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { - Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode @@ -89,7 +89,7 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values // HTTPStatusCode asserts that a specified handler returns a specified status code. // -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) +// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { @@ -98,12 +98,12 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va } code, err := httpCode(handler, method, url, values) if err != nil { - Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { - Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code)) + Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful @@ -113,7 +113,10 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, va // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() - req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if len(values) > 0 { + url += "?" + values.Encode() + } + req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } @@ -124,7 +127,7 @@ func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) s // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { @@ -135,7 +138,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, contains := strings.Contains(body, fmt.Sprint(str)) if !contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains @@ -144,7 +147,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { @@ -155,7 +158,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin contains := strings.Contains(body, fmt.Sprint(str)) if contains { - Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains diff --git a/vendor/github.com/stretchr/testify/mock/doc.go b/vendor/github.com/stretchr/testify/mock/doc.go index 7324128ef1..d6b3c844cc 100644 --- a/vendor/github.com/stretchr/testify/mock/doc.go +++ b/vendor/github.com/stretchr/testify/mock/doc.go @@ -1,17 +1,17 @@ // Package mock provides a system by which it is possible to mock your objects // and verify calls are happening as expected. // -// Example Usage +// # Example Usage // // The mock package provides an object, Mock, that tracks activity on another object. It is usually // embedded into a test object as shown below: // -// type MyTestObject struct { -// // add a Mock object instance -// mock.Mock +// type MyTestObject struct { +// // add a Mock object instance +// mock.Mock // -// // other fields go here as normal -// } +// // other fields go here as normal +// } // // When implementing the methods of an interface, you wire your functions up // to call the Mock.Called(args...) method, and return the appropriate values. @@ -19,25 +19,25 @@ // For example, to mock a method that saves the name and age of a person and returns // the year of their birth or an error, you might write this: // -// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { -// args := o.Called(firstname, lastname, age) -// return args.Int(0), args.Error(1) -// } +// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { +// args := o.Called(firstname, lastname, age) +// return args.Int(0), args.Error(1) +// } // // The Int, Error and Bool methods are examples of strongly typed getters that take the argument // index position. Given this argument list: // -// (12, true, "Something") +// (12, true, "Something") // // You could read them out strongly typed like this: // -// args.Int(0) -// args.Bool(1) -// args.String(2) +// args.Int(0) +// args.Bool(1) +// args.String(2) // // For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: // -// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) +// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) // // This may cause a panic if the object you are getting is nil (the type assertion will fail), in those // cases you should check for nil first. diff --git a/vendor/github.com/stretchr/testify/mock/mock.go b/vendor/github.com/stretchr/testify/mock/mock.go index f0af8246cf..213bde2ea6 100644 --- a/vendor/github.com/stretchr/testify/mock/mock.go +++ b/vendor/github.com/stretchr/testify/mock/mock.go @@ -3,6 +3,7 @@ package mock import ( "errors" "fmt" + "path" "reflect" "regexp" "runtime" @@ -13,9 +14,13 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" "github.com/stretchr/objx" + "github.com/stretchr/testify/assert" ) +// regex for GCCGO functions +var gccgoRE = regexp.MustCompile(`\.pN\d+_`) + // TestingT is an interface wrapper around *testing.T type TestingT interface { Logf(format string, args ...interface{}) @@ -99,7 +104,7 @@ func (c *Call) unlock() { // Return specifies the return arguments for the expectation. // -// Mock.On("DoSomething").Return(errors.New("failed")) +// Mock.On("DoSomething").Return(errors.New("failed")) func (c *Call) Return(returnArguments ...interface{}) *Call { c.lock() defer c.unlock() @@ -109,9 +114,9 @@ func (c *Call) Return(returnArguments ...interface{}) *Call { return c } -// Panic specifies if the functon call should fail and the panic message +// Panic specifies if the function call should fail and the panic message // -// Mock.On("DoSomething").Panic("test panic") +// Mock.On("DoSomething").Panic("test panic") func (c *Call) Panic(msg string) *Call { c.lock() defer c.unlock() @@ -121,24 +126,24 @@ func (c *Call) Panic(msg string) *Call { return c } -// Once indicates that that the mock should only return the value once. +// Once indicates that the mock should only return the value once. // -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() func (c *Call) Once() *Call { return c.Times(1) } -// Twice indicates that that the mock should only return the value twice. +// Twice indicates that the mock should only return the value twice. // -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() func (c *Call) Twice() *Call { return c.Times(2) } -// Times indicates that that the mock should only return the indicated number +// Times indicates that the mock should only return the indicated number // of times. // -// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) func (c *Call) Times(i int) *Call { c.lock() defer c.unlock() @@ -149,7 +154,7 @@ func (c *Call) Times(i int) *Call { // WaitUntil sets the channel that will block the mock's return until its closed // or a message is received. // -// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) +// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second)) func (c *Call) WaitUntil(w <-chan time.Time) *Call { c.lock() defer c.unlock() @@ -159,7 +164,7 @@ func (c *Call) WaitUntil(w <-chan time.Time) *Call { // After sets how long to block until the call returns // -// Mock.On("MyMethod", arg1, arg2).After(time.Second) +// Mock.On("MyMethod", arg1, arg2).After(time.Second) func (c *Call) After(d time.Duration) *Call { c.lock() defer c.unlock() @@ -171,10 +176,10 @@ func (c *Call) After(d time.Duration) *Call { // mocking a method (such as an unmarshaler) that takes a pointer to a struct and // sets properties in such struct // -// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) { -// arg := args.Get(0).(*map[string]interface{}) -// arg["foo"] = "bar" -// }) +// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}")).Return().Run(func(args Arguments) { +// arg := args.Get(0).(*map[string]interface{}) +// arg["foo"] = "bar" +// }) func (c *Call) Run(fn func(args Arguments)) *Call { c.lock() defer c.unlock() @@ -194,16 +199,18 @@ func (c *Call) Maybe() *Call { // On chains a new expectation description onto the mocked interface. This // allows syntax like. // -// Mock. -// On("MyMethod", 1).Return(nil). -// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error")) +// Mock. +// On("MyMethod", 1).Return(nil). +// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error")) +// //go:noinline func (c *Call) On(methodName string, arguments ...interface{}) *Call { return c.Parent.On(methodName, arguments...) } // Unset removes a mock handler from being called. -// test.On("func", mock.Anything).Unset() +// +// test.On("func", mock.Anything).Unset() func (c *Call) Unset() *Call { var unlockOnce sync.Once @@ -218,16 +225,22 @@ func (c *Call) Unset() *Call { foundMatchingCall := false - for i, call := range c.Parent.ExpectedCalls { + // in-place filter slice for calls to be removed - iterate from 0'th to last skipping unnecessary ones + var index int // write index + for _, call := range c.Parent.ExpectedCalls { if call.Method == c.Method { _, diffCount := call.Arguments.Diff(c.Arguments) if diffCount == 0 { foundMatchingCall = true - // Remove from ExpectedCalls - c.Parent.ExpectedCalls = append(c.Parent.ExpectedCalls[:i], c.Parent.ExpectedCalls[i+1:]...) + // Remove from ExpectedCalls - just skip it + continue } } + c.Parent.ExpectedCalls[index] = call + index++ } + // trim slice up to last copied index + c.Parent.ExpectedCalls = c.Parent.ExpectedCalls[:index] if !foundMatchingCall { unlockOnce.Do(c.unlock) @@ -243,9 +256,9 @@ func (c *Call) Unset() *Call { // calls have been called as expected. The referenced calls may be from the // same mock instance and/or other mock instances. // -// Mock.On("Do").Return(nil).Notbefore( -// Mock.On("Init").Return(nil) -// ) +// Mock.On("Do").Return(nil).Notbefore( +// Mock.On("Init").Return(nil) +// ) func (c *Call) NotBefore(calls ...*Call) *Call { c.lock() defer c.unlock() @@ -328,7 +341,7 @@ func (m *Mock) fail(format string, args ...interface{}) { // On starts a description of an expectation of the specified method // being called. // -// Mock.On("MyMethod", arg1, arg2) +// Mock.On("MyMethod", arg1, arg2) func (m *Mock) On(methodName string, arguments ...interface{}) *Call { for _, arg := range arguments { if v := reflect.ValueOf(arg); v.Kind() == reflect.Func { @@ -418,6 +431,10 @@ func callString(method string, arguments Arguments, includeArgumentValues bool) if includeArgumentValues { var argVals []string for argIndex, arg := range arguments { + if _, ok := arg.(*FunctionalOptionsArgument); ok { + argVals = append(argVals, fmt.Sprintf("%d: %s", argIndex, arg)) + continue + } argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg)) } argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t")) @@ -441,9 +458,8 @@ func (m *Mock) Called(arguments ...interface{}) Arguments { // For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock // uses interface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree // With GCCGO we need to remove interface information starting from pN
. - re := regexp.MustCompile("\\.pN\\d+_") - if re.MatchString(functionPath) { - functionPath = re.Split(functionPath, -1)[0] + if gccgoRE.MatchString(functionPath) { + functionPath = gccgoRE.Split(functionPath, -1)[0] } parts := strings.Split(functionPath, ".") functionName := parts[len(parts)-1] @@ -460,7 +476,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen found, call := m.findExpectedCall(methodName, arguments...) if found < 0 { - // expected call found but it has already been called with repeatable times + // expected call found, but it has already been called with repeatable times if call != nil { m.mutex.Unlock() m.fail("\nassert: mock: The method has been called over %d times.\n\tEither do one more Mock.On(\"%s\").Return(...), or remove extra call.\n\tThis call was unexpected:\n\t\t%s\n\tat: %s", call.totalCalls, methodName, callString(methodName, arguments, true), assert.CallerInfo()) @@ -549,7 +565,7 @@ func (m *Mock) MethodCalled(methodName string, arguments ...interface{}) Argumen Assertions */ -type assertExpectationser interface { +type assertExpectationiser interface { AssertExpectations(TestingT) bool } @@ -566,7 +582,7 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { t.Logf("Deprecated mock.AssertExpectationsForObjects(myMock.Mock) use mock.AssertExpectationsForObjects(myMock)") obj = m } - m := obj.(assertExpectationser) + m := obj.(assertExpectationiser) if !m.AssertExpectations(t) { t.Logf("Expectations didn't match for Mock: %+v", reflect.TypeOf(m)) return false @@ -578,6 +594,9 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { // AssertExpectations asserts that everything specified with On and Return was // in fact called as expected. Calls may have occurred in any order. func (m *Mock) AssertExpectations(t TestingT) bool { + if s, ok := t.(interface{ Skipped() bool }); ok && s.Skipped() { + return true + } if h, ok := t.(tHelper); ok { h.Helper() } @@ -592,8 +611,8 @@ func (m *Mock) AssertExpectations(t TestingT) bool { satisfied, reason := m.checkExpectation(expectedCall) if !satisfied { failedExpectations++ + t.Logf(reason) } - t.Logf(reason) } if failedExpectations != 0 { @@ -744,24 +763,33 @@ const ( Anything = "mock.Anything" ) -// AnythingOfTypeArgument is a string that contains the type of an argument +// AnythingOfTypeArgument contains the type of an argument // for use when type checking. Used in Diff and Assert. -type AnythingOfTypeArgument string +// +// Deprecated: this is an implementation detail that must not be used. Use [AnythingOfType] instead. +type AnythingOfTypeArgument = anythingOfTypeArgument -// AnythingOfType returns an AnythingOfTypeArgument object containing the -// name of the type to check for. Used in Diff and Assert. +// anythingOfTypeArgument is a string that contains the type of an argument +// for use when type checking. Used in Diff and Assert. +type anythingOfTypeArgument string + +// AnythingOfType returns a special value containing the +// name of the type to check for. The type name will be matched against the type name returned by [reflect.Type.String]. +// +// Used in Diff and Assert. // // For example: +// // Assert(t, AnythingOfType("string"), AnythingOfType("int")) func AnythingOfType(t string) AnythingOfTypeArgument { - return AnythingOfTypeArgument(t) + return anythingOfTypeArgument(t) } // IsTypeArgument is a struct that contains the type of an argument // for use when type checking. This is an alternative to AnythingOfType. // Used in Diff and Assert. type IsTypeArgument struct { - t interface{} + t reflect.Type } // IsType returns an IsTypeArgument object containing the type to check for. @@ -771,7 +799,35 @@ type IsTypeArgument struct { // For example: // Assert(t, IsType(""), IsType(0)) func IsType(t interface{}) *IsTypeArgument { - return &IsTypeArgument{t: t} + return &IsTypeArgument{t: reflect.TypeOf(t)} +} + +// FunctionalOptionsArgument is a struct that contains the type and value of an functional option argument +// for use when type checking. +type FunctionalOptionsArgument struct { + value interface{} +} + +// String returns the string representation of FunctionalOptionsArgument +func (f *FunctionalOptionsArgument) String() string { + var name string + tValue := reflect.ValueOf(f.value) + if tValue.Len() > 0 { + name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() + } + + return strings.Replace(fmt.Sprintf("%#v", f.value), "[]interface {}", name, 1) +} + +// FunctionalOptions returns an FunctionalOptionsArgument object containing the functional option type +// and the values to check of +// +// For example: +// Assert(t, FunctionalOptions("[]foo.FunctionalOption", foo.Opt1(), foo.Opt2())) +func FunctionalOptions(value ...interface{}) *FunctionalOptionsArgument { + return &FunctionalOptionsArgument{ + value: value, + } } // argumentMatcher performs custom argument matching, returning whether or @@ -907,29 +963,54 @@ func (args Arguments) Diff(objects []interface{}) (string, int) { differences++ output = fmt.Sprintf("%s\t%d: FAIL: %s not matched by %s\n", output, i, actualFmt, matcher) } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { - // type checking - if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) - } - } else if reflect.TypeOf(expected) == reflect.TypeOf((*IsTypeArgument)(nil)) { - t := expected.(*IsTypeArgument).t - if reflect.TypeOf(t) != reflect.TypeOf(actual) { - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, reflect.TypeOf(t).Name(), reflect.TypeOf(actual).Name(), actualFmt) - } } else { - // normal checking + switch expected := expected.(type) { + case anythingOfTypeArgument: + // type checking + if reflect.TypeOf(actual).Name() != string(expected) && reflect.TypeOf(actual).String() != string(expected) { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actualFmt) + } + case *IsTypeArgument: + actualT := reflect.TypeOf(actual) + if actualT != expected.t { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, expected.t.Name(), actualT.Name(), actualFmt) + } + case *FunctionalOptionsArgument: + t := expected.value - if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { - // match - output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) - } else { - // not match - differences++ - output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) + var name string + tValue := reflect.ValueOf(t) + if tValue.Len() > 0 { + name = "[]" + reflect.TypeOf(tValue.Index(0).Interface()).String() + } + + tName := reflect.TypeOf(t).Name() + if name != reflect.TypeOf(actual).String() && tValue.Len() != 0 { + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: type %s != type %s - %s\n", output, i, tName, reflect.TypeOf(actual).Name(), actualFmt) + } else { + if ef, af := assertOpts(t, actual); ef == "" && af == "" { + // match + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, tName, tName) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, af, ef) + } + } + + default: + if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { + // match + output = fmt.Sprintf("%s\t%d: PASS: %s == %s\n", output, i, actualFmt, expectedFmt) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: FAIL: %s != %s\n", output, i, actualFmt, expectedFmt) + } } } @@ -1096,3 +1177,65 @@ var spewConfig = spew.ConfigState{ type tHelper interface { Helper() } + +func assertOpts(expected, actual interface{}) (expectedFmt, actualFmt string) { + expectedOpts := reflect.ValueOf(expected) + actualOpts := reflect.ValueOf(actual) + var expectedNames []string + for i := 0; i < expectedOpts.Len(); i++ { + expectedNames = append(expectedNames, funcName(expectedOpts.Index(i).Interface())) + } + var actualNames []string + for i := 0; i < actualOpts.Len(); i++ { + actualNames = append(actualNames, funcName(actualOpts.Index(i).Interface())) + } + if !assert.ObjectsAreEqual(expectedNames, actualNames) { + expectedFmt = fmt.Sprintf("%v", expectedNames) + actualFmt = fmt.Sprintf("%v", actualNames) + return + } + + for i := 0; i < expectedOpts.Len(); i++ { + expectedOpt := expectedOpts.Index(i).Interface() + actualOpt := actualOpts.Index(i).Interface() + + expectedFunc := expectedNames[i] + actualFunc := actualNames[i] + if expectedFunc != actualFunc { + expectedFmt = expectedFunc + actualFmt = actualFunc + return + } + + ot := reflect.TypeOf(expectedOpt) + var expectedValues []reflect.Value + var actualValues []reflect.Value + if ot.NumIn() == 0 { + return + } + + for i := 0; i < ot.NumIn(); i++ { + vt := ot.In(i).Elem() + expectedValues = append(expectedValues, reflect.New(vt)) + actualValues = append(actualValues, reflect.New(vt)) + } + + reflect.ValueOf(expectedOpt).Call(expectedValues) + reflect.ValueOf(actualOpt).Call(actualValues) + + for i := 0; i < ot.NumIn(); i++ { + if !assert.ObjectsAreEqual(expectedValues[i].Interface(), actualValues[i].Interface()) { + expectedFmt = fmt.Sprintf("%s %+v", expectedNames[i], expectedValues[i].Interface()) + actualFmt = fmt.Sprintf("%s %+v", expectedNames[i], actualValues[i].Interface()) + return + } + } + } + + return "", "" +} + +func funcName(opt interface{}) string { + n := runtime.FuncForPC(reflect.ValueOf(opt).Pointer()).Name() + return strings.TrimSuffix(path.Base(n), path.Ext(n)) +} diff --git a/vendor/github.com/stretchr/testify/require/doc.go b/vendor/github.com/stretchr/testify/require/doc.go index 169de39221..9684347245 100644 --- a/vendor/github.com/stretchr/testify/require/doc.go +++ b/vendor/github.com/stretchr/testify/require/doc.go @@ -1,24 +1,25 @@ // Package require implements the same assertions as the `assert` package but // stops test execution when a test fails. // -// Example Usage +// # Example Usage // // The following is a complete example using require in a standard test function: -// import ( -// "testing" -// "github.com/stretchr/testify/require" -// ) // -// func TestSomething(t *testing.T) { +// import ( +// "testing" +// "github.com/stretchr/testify/require" +// ) // -// var a string = "Hello" -// var b string = "Hello" +// func TestSomething(t *testing.T) { // -// require.Equal(t, a, b, "The two words should be the same.") +// var a string = "Hello" +// var b string = "Hello" // -// } +// require.Equal(t, a, b, "The two words should be the same.") // -// Assertions +// } +// +// # Assertions // // The `require` package have same global functions as in the `assert` package, // but instead of returning a boolean result they call `t.FailNow()`. diff --git a/vendor/github.com/stretchr/testify/require/require.go b/vendor/github.com/stretchr/testify/require/require.go index 880853f5a2..506a82f807 100644 --- a/vendor/github.com/stretchr/testify/require/require.go +++ b/vendor/github.com/stretchr/testify/require/require.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -37,9 +34,9 @@ func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interfac // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// assert.Contains(t, "Hello World", "World") -// assert.Contains(t, ["Hello", "World"], "World") -// assert.Contains(t, {"Hello": "World"}, "Hello") +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -53,9 +50,9 @@ func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...int // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") -// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") -// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -123,7 +120,7 @@ func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// assert.Empty(t, obj) +// assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -137,7 +134,7 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// assert.Emptyf(t, obj, "error message %s", "formatted") +// assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -150,7 +147,7 @@ func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { // Equal asserts that two objects are equal. // -// assert.Equal(t, 123, 123) +// assert.Equal(t, 123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -168,8 +165,8 @@ func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...i // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// assert.EqualError(t, err, expectedErrorString) +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -183,8 +180,8 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -195,10 +192,50 @@ func EqualErrorf(t TestingT, theError error, errString string, msg string, args t.FailNow() } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualExportedValues asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true +// assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false +func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) { + return + } + t.FailNow() +} + +// EqualExportedValuesf asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true +// assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false +func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EqualExportedValuesf(t, expected, actual, msg, args...) { + return + } + t.FailNow() +} + +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // -// assert.EqualValues(t, uint32(123), int32(123)) +// assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -209,10 +246,10 @@ func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArg t.FailNow() } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // -// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") +// assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -225,7 +262,7 @@ func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg stri // Equalf asserts that two objects are equal. // -// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -242,10 +279,10 @@ func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, ar // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Error(t, err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } func Error(t TestingT, err error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -283,8 +320,8 @@ func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...int // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// assert.ErrorContains(t, err, expectedErrorSubString) +// actualObj, err := SomeFunction() +// assert.ErrorContains(t, err, expectedErrorSubString) func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -298,8 +335,8 @@ func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...in // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -336,10 +373,10 @@ func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if assert.Errorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } func Errorf(t TestingT, err error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -353,7 +390,7 @@ func Errorf(t TestingT, err error, msg string, args ...interface{}) { // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -364,10 +401,66 @@ func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick t t.FailNow() } +// EventuallyWithT asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// assert.EventuallyWithT(t, func(c *assert.CollectT) { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) { + return + } + t.FailNow() +} + +// EventuallyWithTf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) { + return + } + t.FailNow() +} + // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -380,7 +473,7 @@ func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick // Exactly asserts that two objects are equal in value and type. // -// assert.Exactly(t, int32(123), int64(123)) +// assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -393,7 +486,7 @@ func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs .. // Exactlyf asserts that two objects are equal in value and type. // -// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") +// assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -450,7 +543,7 @@ func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { // False asserts that the specified value is false. // -// assert.False(t, myBool) +// assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -463,7 +556,7 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) { // Falsef asserts that the specified value is false. // -// assert.Falsef(t, myBool, "error message %s", "formatted") +// assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -500,9 +593,9 @@ func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { // Greater asserts that the first element is greater than the second // -// assert.Greater(t, 2, 1) -// assert.Greater(t, float64(2), float64(1)) -// assert.Greater(t, "b", "a") +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -515,10 +608,10 @@ func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface // GreaterOrEqual asserts that the first element is greater than or equal to the second // -// assert.GreaterOrEqual(t, 2, 1) -// assert.GreaterOrEqual(t, 2, 2) -// assert.GreaterOrEqual(t, "b", "a") -// assert.GreaterOrEqual(t, "b", "b") +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -531,10 +624,10 @@ func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...in // GreaterOrEqualf asserts that the first element is greater than or equal to the second // -// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") -// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -547,9 +640,9 @@ func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, arg // Greaterf asserts that the first element is greater than the second // -// assert.Greaterf(t, 2, 1, "error message %s", "formatted") -// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") -// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -563,7 +656,7 @@ func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...in // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { @@ -579,7 +672,7 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url s // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { @@ -595,7 +688,7 @@ func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { @@ -611,7 +704,7 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, ur // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { @@ -626,7 +719,7 @@ func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, u // HTTPError asserts that a specified handler returns an error status code. // -// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -641,7 +734,7 @@ func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, // HTTPErrorf asserts that a specified handler returns an error status code. // -// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -656,7 +749,7 @@ func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, // HTTPRedirect asserts that a specified handler returns a redirect status code. // -// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -671,7 +764,7 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url strin // HTTPRedirectf asserts that a specified handler returns a redirect status code. // -// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -686,7 +779,7 @@ func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url stri // HTTPStatusCode asserts that a specified handler returns a specified status code. // -// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) +// assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { @@ -701,7 +794,7 @@ func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url str // HTTPStatusCodef asserts that a specified handler returns a specified status code. // -// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") +// assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { @@ -716,7 +809,7 @@ func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url st // HTTPSuccess asserts that a specified handler returns a success status code. // -// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -731,7 +824,7 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string // HTTPSuccessf asserts that a specified handler returns a success status code. // -// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -746,7 +839,7 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin // Implements asserts that an object is implemented by the specified interface. // -// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -759,7 +852,7 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg // Implementsf asserts that an object is implemented by the specified interface. // -// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +// assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -772,7 +865,7 @@ func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, ms // InDelta asserts that the two numerals are within delta of each other. // -// assert.InDelta(t, math.Pi, 22/7.0, 0.01) +// assert.InDelta(t, math.Pi, 22/7.0, 0.01) func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -829,7 +922,7 @@ func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta f // InDeltaf asserts that the two numerals are within delta of each other. // -// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -886,9 +979,9 @@ func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon fl // IsDecreasing asserts that the collection is decreasing // -// assert.IsDecreasing(t, []int{2, 1, 0}) -// assert.IsDecreasing(t, []float{2, 1}) -// assert.IsDecreasing(t, []string{"b", "a"}) +// assert.IsDecreasing(t, []int{2, 1, 0}) +// assert.IsDecreasing(t, []float{2, 1}) +// assert.IsDecreasing(t, []string{"b", "a"}) func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -901,9 +994,9 @@ func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { // IsDecreasingf asserts that the collection is decreasing // -// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -916,9 +1009,9 @@ func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface // IsIncreasing asserts that the collection is increasing // -// assert.IsIncreasing(t, []int{1, 2, 3}) -// assert.IsIncreasing(t, []float{1, 2}) -// assert.IsIncreasing(t, []string{"a", "b"}) +// assert.IsIncreasing(t, []int{1, 2, 3}) +// assert.IsIncreasing(t, []float{1, 2}) +// assert.IsIncreasing(t, []string{"a", "b"}) func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -931,9 +1024,9 @@ func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { // IsIncreasingf asserts that the collection is increasing // -// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -946,9 +1039,9 @@ func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface // IsNonDecreasing asserts that the collection is not decreasing // -// assert.IsNonDecreasing(t, []int{1, 1, 2}) -// assert.IsNonDecreasing(t, []float{1, 2}) -// assert.IsNonDecreasing(t, []string{"a", "b"}) +// assert.IsNonDecreasing(t, []int{1, 1, 2}) +// assert.IsNonDecreasing(t, []float{1, 2}) +// assert.IsNonDecreasing(t, []string{"a", "b"}) func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -961,9 +1054,9 @@ func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) // IsNonDecreasingf asserts that the collection is not decreasing // -// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") -// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") +// assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -976,9 +1069,9 @@ func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interf // IsNonIncreasing asserts that the collection is not increasing // -// assert.IsNonIncreasing(t, []int{2, 1, 1}) -// assert.IsNonIncreasing(t, []float{2, 1}) -// assert.IsNonIncreasing(t, []string{"b", "a"}) +// assert.IsNonIncreasing(t, []int{2, 1, 1}) +// assert.IsNonIncreasing(t, []float{2, 1}) +// assert.IsNonIncreasing(t, []string{"b", "a"}) func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -991,9 +1084,9 @@ func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) // IsNonIncreasingf asserts that the collection is not increasing // -// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") -// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") +// assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1028,7 +1121,7 @@ func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg strin // JSONEq asserts that two JSON strings are equivalent. // -// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1041,7 +1134,7 @@ func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{ // JSONEqf asserts that two JSON strings are equivalent. // -// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1055,7 +1148,7 @@ func JSONEqf(t TestingT, expected string, actual string, msg string, args ...int // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // -// assert.Len(t, mySlice, 3) +// assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1069,7 +1162,7 @@ func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // -// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1082,9 +1175,9 @@ func Lenf(t TestingT, object interface{}, length int, msg string, args ...interf // Less asserts that the first element is less than the second // -// assert.Less(t, 1, 2) -// assert.Less(t, float64(1), float64(2)) -// assert.Less(t, "a", "b") +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1097,10 +1190,10 @@ func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) // LessOrEqual asserts that the first element is less than or equal to the second // -// assert.LessOrEqual(t, 1, 2) -// assert.LessOrEqual(t, 2, 2) -// assert.LessOrEqual(t, "a", "b") -// assert.LessOrEqual(t, "b", "b") +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1113,10 +1206,10 @@ func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...inter // LessOrEqualf asserts that the first element is less than or equal to the second // -// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") -// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") -// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1129,9 +1222,9 @@ func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args . // Lessf asserts that the first element is less than the second // -// assert.Lessf(t, 1, 2, "error message %s", "formatted") -// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") -// assert.Lessf(t, "a", "b", "error message %s", "formatted") +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") +// assert.Lessf(t, "a", "b", "error message %s", "formatted") func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1144,8 +1237,8 @@ func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...inter // Negative asserts that the specified element is negative // -// assert.Negative(t, -1) -// assert.Negative(t, -1.23) +// assert.Negative(t, -1) +// assert.Negative(t, -1.23) func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1158,8 +1251,8 @@ func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { // Negativef asserts that the specified element is negative // -// assert.Negativef(t, -1, "error message %s", "formatted") -// assert.Negativef(t, -1.23, "error message %s", "formatted") +// assert.Negativef(t, -1, "error message %s", "formatted") +// assert.Negativef(t, -1.23, "error message %s", "formatted") func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1173,7 +1266,7 @@ func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) +// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1187,7 +1280,7 @@ func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.D // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1200,7 +1293,7 @@ func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time. // Nil asserts that the specified object is nil. // -// assert.Nil(t, err) +// assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1213,7 +1306,7 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { // Nilf asserts that the specified object is nil. // -// assert.Nilf(t, err, "error message %s", "formatted") +// assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1250,10 +1343,10 @@ func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) { // NoError asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if assert.NoError(t, err) { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } func NoError(t TestingT, err error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1266,10 +1359,10 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) { // NoErrorf asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if assert.NoErrorf(t, err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1307,9 +1400,9 @@ func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) { // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// assert.NotContains(t, "Hello World", "Earth") -// assert.NotContains(t, ["Hello", "World"], "Earth") -// assert.NotContains(t, {"Hello": "World"}, "Earth") +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1323,9 +1416,9 @@ func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ... // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") -// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1339,9 +1432,9 @@ func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, a // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if assert.NotEmpty(t, obj) { -// assert.Equal(t, "two", obj[1]) -// } +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1355,9 +1448,9 @@ func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1370,7 +1463,7 @@ func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) // NotEqual asserts that the specified values are NOT equal. // -// assert.NotEqual(t, obj1, obj2) +// assert.NotEqual(t, obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1386,7 +1479,7 @@ func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs . // NotEqualValues asserts that two objects are not equal even when converted to the same type // -// assert.NotEqualValues(t, obj1, obj2) +// assert.NotEqualValues(t, obj1, obj2) func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1399,7 +1492,7 @@ func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAnd // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // -// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") +// assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1412,7 +1505,7 @@ func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg s // NotEqualf asserts that the specified values are NOT equal. // -// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1450,9 +1543,35 @@ func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interf t.FailNow() } +// NotImplements asserts that an object does not implement the specified interface. +// +// assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) +func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { + return + } + t.FailNow() +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { + return + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // -// assert.NotNil(t, err) +// assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1465,7 +1584,7 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { // NotNilf asserts that the specified object is not nil. // -// assert.NotNilf(t, err, "error message %s", "formatted") +// assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1478,7 +1597,7 @@ func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // -// assert.NotPanics(t, func(){ RemainCalm() }) +// assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1491,7 +1610,7 @@ func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // -// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1504,8 +1623,8 @@ func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interfac // NotRegexp asserts that a specified regexp does not match a string. // -// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") -// assert.NotRegexp(t, "^start", "it's not starting") +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1518,8 +1637,8 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf // NotRegexpf asserts that a specified regexp does not match a string. // -// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +// assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1532,7 +1651,7 @@ func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args .. // NotSame asserts that two pointers do not reference the same object. // -// assert.NotSame(t, ptr1, ptr2) +// assert.NotSame(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1548,7 +1667,7 @@ func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs .. // NotSamef asserts that two pointers do not reference the same object. // -// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") +// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1562,10 +1681,12 @@ func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// assert.NotSubset(t, [1, 3, 4], [1, 2]) +// assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1576,10 +1697,12 @@ func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...i t.FailNow() } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") +// assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1614,7 +1737,7 @@ func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { // Panics asserts that the code inside the specified PanicTestFunc panics. // -// assert.Panics(t, func(){ GoCrazy() }) +// assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1629,7 +1752,7 @@ func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) +// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1644,7 +1767,7 @@ func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAn // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1658,7 +1781,7 @@ func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1672,7 +1795,7 @@ func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, m // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1685,7 +1808,7 @@ func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, // Panicsf asserts that the code inside the specified PanicTestFunc panics. // -// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1698,8 +1821,8 @@ func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{} // Positive asserts that the specified element is positive // -// assert.Positive(t, 1) -// assert.Positive(t, 1.23) +// assert.Positive(t, 1) +// assert.Positive(t, 1.23) func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1712,8 +1835,8 @@ func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { // Positivef asserts that the specified element is positive // -// assert.Positivef(t, 1, "error message %s", "formatted") -// assert.Positivef(t, 1.23, "error message %s", "formatted") +// assert.Positivef(t, 1, "error message %s", "formatted") +// assert.Positivef(t, 1.23, "error message %s", "formatted") func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1726,8 +1849,8 @@ func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { // Regexp asserts that a specified regexp matches a string. // -// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") -// assert.Regexp(t, "start...$", "it's not starting") +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1740,8 +1863,8 @@ func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface // Regexpf asserts that a specified regexp matches a string. // -// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +// assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1754,7 +1877,7 @@ func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...in // Same asserts that two pointers reference the same object. // -// assert.Same(t, ptr1, ptr2) +// assert.Same(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1770,7 +1893,7 @@ func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...in // Samef asserts that two pointers reference the same object. // -// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1784,10 +1907,11 @@ func Samef(t TestingT, expected interface{}, actual interface{}, msg string, arg t.FailNow() } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// assert.Subset(t, [1, 2, 3], [1, 2]) +// assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1798,10 +1922,11 @@ func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...inte t.FailNow() } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") +// assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1814,7 +1939,7 @@ func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args // True asserts that the specified value is true. // -// assert.True(t, myBool) +// assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1827,7 +1952,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) { // Truef asserts that the specified value is true. // -// assert.Truef(t, myBool, "error message %s", "formatted") +// assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1840,7 +1965,7 @@ func Truef(t TestingT, value bool, msg string, args ...interface{}) { // WithinDuration asserts that the two times are within duration delta of each other. // -// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1853,7 +1978,7 @@ func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time // WithinDurationf asserts that the two times are within duration delta of each other. // -// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1866,7 +1991,7 @@ func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta tim // WithinRange asserts that a time is within a time range (inclusive). // -// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) +// assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() @@ -1879,7 +2004,7 @@ func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, m // WithinRangef asserts that a time is within a time range (inclusive). // -// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") +// assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/require/require_forward.go b/vendor/github.com/stretchr/testify/require/require_forward.go index 960bf6f2ca..eee8310a5f 100644 --- a/vendor/github.com/stretchr/testify/require/require_forward.go +++ b/vendor/github.com/stretchr/testify/require/require_forward.go @@ -1,7 +1,4 @@ -/* -* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen -* THIS FILE MUST NOT BE EDITED BY HAND - */ +// Code generated with github.com/stretchr/testify/_codegen; DO NOT EDIT. package require @@ -31,9 +28,9 @@ func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...inte // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// a.Contains("Hello World", "World") -// a.Contains(["Hello", "World"], "World") -// a.Contains({"Hello": "World"}, "Hello") +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -44,9 +41,9 @@ func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs .. // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // -// a.Containsf("Hello World", "World", "error message %s", "formatted") -// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") -// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -99,7 +96,7 @@ func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg st // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// a.Empty(obj) +// a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -110,7 +107,7 @@ func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // -// a.Emptyf(obj, "error message %s", "formatted") +// a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -120,7 +117,7 @@ func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) // Equal asserts that two objects are equal. // -// a.Equal(123, 123) +// a.Equal(123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -135,8 +132,8 @@ func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// a.EqualError(err, expectedErrorString) +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -147,8 +144,8 @@ func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ... // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // -// actualObj, err := SomeFunction() -// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -156,10 +153,44 @@ func (a *Assertions) EqualErrorf(theError error, errString string, msg string, a EqualErrorf(a.t, theError, errString, msg, args...) } -// EqualValues asserts that two objects are equal or convertable to the same types +// EqualExportedValues asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// a.EqualExportedValues(S{1, 2}, S{1, 3}) => true +// a.EqualExportedValues(S{1, 2}, S{2, 3}) => false +func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualExportedValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualExportedValuesf asserts that the types of two objects are equal and their public +// fields are also equal. This is useful for comparing structs that have private fields +// that could potentially differ. +// +// type S struct { +// Exported int +// notExported int +// } +// a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true +// a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false +func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EqualExportedValuesf(a.t, expected, actual, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertible to the same types // and equal. // -// a.EqualValues(uint32(123), int32(123)) +// a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -167,10 +198,10 @@ func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAn EqualValues(a.t, expected, actual, msgAndArgs...) } -// EqualValuesf asserts that two objects are equal or convertable to the same types +// EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // -// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") +// a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -180,7 +211,7 @@ func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg // Equalf asserts that two objects are equal. // -// a.Equalf(123, 123, "error message %s", "formatted") +// a.Equalf(123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality @@ -194,10 +225,10 @@ func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string // Error asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Error(err) { -// assert.Equal(t, expectedError, err) -// } +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -226,8 +257,8 @@ func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args .. // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// a.ErrorContains(err, expectedErrorSubString) +// actualObj, err := SomeFunction() +// a.ErrorContains(err, expectedErrorSubString) func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -238,8 +269,8 @@ func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs . // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // -// actualObj, err := SomeFunction() -// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") +// actualObj, err := SomeFunction() +// a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -267,10 +298,10 @@ func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...inter // Errorf asserts that a function returned an error (i.e. not `nil`). // -// actualObj, err := SomeFunction() -// if a.Errorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedErrorf, err) -// } +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -281,7 +312,7 @@ func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -289,10 +320,60 @@ func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, ti Eventually(a.t, condition, waitFor, tick, msgAndArgs...) } +// EventuallyWithT asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// a.EventuallyWithT(func(c *assert.CollectT) { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// EventuallyWithTf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. In contrast to Eventually, +// it supplies a CollectT to the condition function, so that the condition +// function can use the CollectT to call other assertions. +// The condition is considered "met" if no errors are raised in a tick. +// The supplied CollectT collects all errors from one tick (if there are any). +// If the condition is not met before waitFor, the collected errors of +// the last tick are copied to t. +// +// externalValue := false +// go func() { +// time.Sleep(8*time.Second) +// externalValue = true +// }() +// a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { +// // add assertions as needed; any assertion failure will fail the current tick +// assert.True(c, externalValue, "expected 'externalValue' to be true") +// }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") +func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) +} + // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // -// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -302,7 +383,7 @@ func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, t // Exactly asserts that two objects are equal in value and type. // -// a.Exactly(int32(123), int64(123)) +// a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -312,7 +393,7 @@ func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArg // Exactlyf asserts that two objects are equal in value and type. // -// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") +// a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -354,7 +435,7 @@ func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{ // False asserts that the specified value is false. // -// a.False(myBool) +// a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -364,7 +445,7 @@ func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { // Falsef asserts that the specified value is false. // -// a.Falsef(myBool, "error message %s", "formatted") +// a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -392,9 +473,9 @@ func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { // Greater asserts that the first element is greater than the second // -// a.Greater(2, 1) -// a.Greater(float64(2), float64(1)) -// a.Greater("b", "a") +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -404,10 +485,10 @@ func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...inter // GreaterOrEqual asserts that the first element is greater than or equal to the second // -// a.GreaterOrEqual(2, 1) -// a.GreaterOrEqual(2, 2) -// a.GreaterOrEqual("b", "a") -// a.GreaterOrEqual("b", "b") +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -417,10 +498,10 @@ func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs . // GreaterOrEqualf asserts that the first element is greater than or equal to the second // -// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") -// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") -// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") -// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -430,9 +511,9 @@ func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, // Greaterf asserts that the first element is greater than the second // -// a.Greaterf(2, 1, "error message %s", "formatted") -// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") -// a.Greaterf("b", "a", "error message %s", "formatted") +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2), float64(1), "error message %s", "formatted") +// a.Greaterf("b", "a", "error message %s", "formatted") func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -443,7 +524,7 @@ func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args . // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { @@ -456,7 +537,7 @@ func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, u // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // -// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { @@ -469,7 +550,7 @@ func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { @@ -482,7 +563,7 @@ func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // -// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { @@ -494,7 +575,7 @@ func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method strin // HTTPError asserts that a specified handler returns an error status code. // -// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -506,7 +587,7 @@ func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url stri // HTTPErrorf asserts that a specified handler returns an error status code. // -// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -518,7 +599,7 @@ func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url str // HTTPRedirect asserts that a specified handler returns a redirect status code. // -// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -530,7 +611,7 @@ func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url s // HTTPRedirectf asserts that a specified handler returns a redirect status code. // -// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -542,7 +623,7 @@ func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url // HTTPStatusCode asserts that a specified handler returns a specified status code. // -// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) +// a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { @@ -554,7 +635,7 @@ func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url // HTTPStatusCodef asserts that a specified handler returns a specified status code. // -// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") +// a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { @@ -566,7 +647,7 @@ func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, ur // HTTPSuccess asserts that a specified handler returns a success status code. // -// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { @@ -578,7 +659,7 @@ func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url st // HTTPSuccessf asserts that a specified handler returns a success status code. // -// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { @@ -590,7 +671,7 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s // Implements asserts that an object is implemented by the specified interface. // -// a.Implements((*MyInterface)(nil), new(MyObject)) +// a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -600,7 +681,7 @@ func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, // Implementsf asserts that an object is implemented by the specified interface. // -// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +// a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -610,7 +691,7 @@ func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{} // InDelta asserts that the two numerals are within delta of each other. // -// a.InDelta(math.Pi, 22/7.0, 0.01) +// a.InDelta(math.Pi, 22/7.0, 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -652,7 +733,7 @@ func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, del // InDeltaf asserts that the two numerals are within delta of each other. // -// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -694,9 +775,9 @@ func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilo // IsDecreasing asserts that the collection is decreasing // -// a.IsDecreasing([]int{2, 1, 0}) -// a.IsDecreasing([]float{2, 1}) -// a.IsDecreasing([]string{"b", "a"}) +// a.IsDecreasing([]int{2, 1, 0}) +// a.IsDecreasing([]float{2, 1}) +// a.IsDecreasing([]string{"b", "a"}) func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -706,9 +787,9 @@ func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) // IsDecreasingf asserts that the collection is decreasing // -// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") -// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") +// a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") +// a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -718,9 +799,9 @@ func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...inter // IsIncreasing asserts that the collection is increasing // -// a.IsIncreasing([]int{1, 2, 3}) -// a.IsIncreasing([]float{1, 2}) -// a.IsIncreasing([]string{"a", "b"}) +// a.IsIncreasing([]int{1, 2, 3}) +// a.IsIncreasing([]float{1, 2}) +// a.IsIncreasing([]string{"a", "b"}) func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -730,9 +811,9 @@ func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) // IsIncreasingf asserts that the collection is increasing // -// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") -// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") +// a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") +// a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -742,9 +823,9 @@ func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...inter // IsNonDecreasing asserts that the collection is not decreasing // -// a.IsNonDecreasing([]int{1, 1, 2}) -// a.IsNonDecreasing([]float{1, 2}) -// a.IsNonDecreasing([]string{"a", "b"}) +// a.IsNonDecreasing([]int{1, 1, 2}) +// a.IsNonDecreasing([]float{1, 2}) +// a.IsNonDecreasing([]string{"a", "b"}) func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -754,9 +835,9 @@ func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface // IsNonDecreasingf asserts that the collection is not decreasing // -// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") -// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") +// a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") +// a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -766,9 +847,9 @@ func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...in // IsNonIncreasing asserts that the collection is not increasing // -// a.IsNonIncreasing([]int{2, 1, 1}) -// a.IsNonIncreasing([]float{2, 1}) -// a.IsNonIncreasing([]string{"b", "a"}) +// a.IsNonIncreasing([]int{2, 1, 1}) +// a.IsNonIncreasing([]float{2, 1}) +// a.IsNonIncreasing([]string{"b", "a"}) func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -778,9 +859,9 @@ func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface // IsNonIncreasingf asserts that the collection is not increasing // -// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") -// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") +// a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") +// a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -806,7 +887,7 @@ func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg s // JSONEq asserts that two JSON strings are equivalent. // -// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -816,7 +897,7 @@ func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interf // JSONEqf asserts that two JSON strings are equivalent. // -// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -827,7 +908,7 @@ func (a *Assertions) JSONEqf(expected string, actual string, msg string, args .. // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // -// a.Len(mySlice, 3) +// a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -838,7 +919,7 @@ func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // -// a.Lenf(mySlice, 3, "error message %s", "formatted") +// a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -848,9 +929,9 @@ func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...in // Less asserts that the first element is less than the second // -// a.Less(1, 2) -// a.Less(float64(1), float64(2)) -// a.Less("a", "b") +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -860,10 +941,10 @@ func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interfac // LessOrEqual asserts that the first element is less than or equal to the second // -// a.LessOrEqual(1, 2) -// a.LessOrEqual(2, 2) -// a.LessOrEqual("a", "b") -// a.LessOrEqual("b", "b") +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -873,10 +954,10 @@ func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...i // LessOrEqualf asserts that the first element is less than or equal to the second // -// a.LessOrEqualf(1, 2, "error message %s", "formatted") -// a.LessOrEqualf(2, 2, "error message %s", "formatted") -// a.LessOrEqualf("a", "b", "error message %s", "formatted") -// a.LessOrEqualf("b", "b", "error message %s", "formatted") +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -886,9 +967,9 @@ func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, ar // Lessf asserts that the first element is less than the second // -// a.Lessf(1, 2, "error message %s", "formatted") -// a.Lessf(float64(1), float64(2), "error message %s", "formatted") -// a.Lessf("a", "b", "error message %s", "formatted") +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1), float64(2), "error message %s", "formatted") +// a.Lessf("a", "b", "error message %s", "formatted") func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -898,8 +979,8 @@ func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...i // Negative asserts that the specified element is negative // -// a.Negative(-1) -// a.Negative(-1.23) +// a.Negative(-1) +// a.Negative(-1.23) func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -909,8 +990,8 @@ func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { // Negativef asserts that the specified element is negative // -// a.Negativef(-1, "error message %s", "formatted") -// a.Negativef(-1.23, "error message %s", "formatted") +// a.Negativef(-1, "error message %s", "formatted") +// a.Negativef(-1.23, "error message %s", "formatted") func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -921,7 +1002,7 @@ func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) +// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -932,7 +1013,7 @@ func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick ti // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // -// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -942,7 +1023,7 @@ func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick t // Nil asserts that the specified object is nil. // -// a.Nil(err) +// a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -952,7 +1033,7 @@ func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { // Nilf asserts that the specified object is nil. // -// a.Nilf(err, "error message %s", "formatted") +// a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -980,10 +1061,10 @@ func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) // NoError asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if a.NoError(err) { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -993,10 +1074,10 @@ func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { // NoErrorf asserts that a function returned no error (i.e. `nil`). // -// actualObj, err := SomeFunction() -// if a.NoErrorf(err, "error message %s", "formatted") { -// assert.Equal(t, expectedObj, actualObj) -// } +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1025,9 +1106,9 @@ func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// a.NotContains("Hello World", "Earth") -// a.NotContains(["Hello", "World"], "Earth") -// a.NotContains({"Hello": "World"}, "Earth") +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1038,9 +1119,9 @@ func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // -// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") -// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") -// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1051,9 +1132,9 @@ func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg strin // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if a.NotEmpty(obj) { -// assert.Equal(t, "two", obj[1]) -// } +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1064,9 +1145,9 @@ func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // -// if a.NotEmptyf(obj, "error message %s", "formatted") { -// assert.Equal(t, "two", obj[1]) -// } +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1076,7 +1157,7 @@ func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface // NotEqual asserts that the specified values are NOT equal. // -// a.NotEqual(obj1, obj2) +// a.NotEqual(obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1089,7 +1170,7 @@ func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndAr // NotEqualValues asserts that two objects are not equal even when converted to the same type // -// a.NotEqualValues(obj1, obj2) +// a.NotEqualValues(obj1, obj2) func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1099,7 +1180,7 @@ func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, ms // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // -// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") +// a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1109,7 +1190,7 @@ func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, m // NotEqualf asserts that the specified values are NOT equal. // -// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). @@ -1138,9 +1219,29 @@ func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...in NotErrorIsf(a.t, err, target, msg, args...) } +// NotImplements asserts that an object does not implement the specified interface. +// +// a.NotImplements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplements(a.t, interfaceObject, object, msgAndArgs...) +} + +// NotImplementsf asserts that an object does not implement the specified interface. +// +// a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") +func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotImplementsf(a.t, interfaceObject, object, msg, args...) +} + // NotNil asserts that the specified object is not nil. // -// a.NotNil(err) +// a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1150,7 +1251,7 @@ func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { // NotNilf asserts that the specified object is not nil. // -// a.NotNilf(err, "error message %s", "formatted") +// a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1160,7 +1261,7 @@ func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{} // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // -// a.NotPanics(func(){ RemainCalm() }) +// a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1170,7 +1271,7 @@ func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{} // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // -// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1180,8 +1281,8 @@ func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...inte // NotRegexp asserts that a specified regexp does not match a string. // -// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") -// a.NotRegexp("^start", "it's not starting") +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1191,8 +1292,8 @@ func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...in // NotRegexpf asserts that a specified regexp does not match a string. // -// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") -// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +// a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1202,7 +1303,7 @@ func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, arg // NotSame asserts that two pointers do not reference the same object. // -// a.NotSame(ptr1, ptr2) +// a.NotSame(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1215,7 +1316,7 @@ func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArg // NotSamef asserts that two pointers do not reference the same object. // -// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") +// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1226,10 +1327,12 @@ func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg stri NotSamef(a.t, expected, actual, msg, args...) } -// NotSubset asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubset asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +// a.NotSubset([1, 3, 4], [1, 2]) +// a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1237,10 +1340,12 @@ func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs NotSubset(a.t, list, subset, msgAndArgs...) } -// NotSubsetf asserts that the specified list(array, slice...) contains not all -// elements given in the specified subset(array, slice...). +// NotSubsetf asserts that the specified list(array, slice...) or map does NOT +// contain all elements given in the specified subset list(array, slice...) or +// map. // -// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +// a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") +// a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1266,7 +1371,7 @@ func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { // Panics asserts that the code inside the specified PanicTestFunc panics. // -// a.Panics(func(){ GoCrazy() }) +// a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1278,7 +1383,7 @@ func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// a.PanicsWithError("crazy error", func(){ GoCrazy() }) +// a.PanicsWithError("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1290,7 +1395,7 @@ func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, m // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // -// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1301,7 +1406,7 @@ func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1312,7 +1417,7 @@ func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFun // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // -// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1322,7 +1427,7 @@ func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFu // Panicsf asserts that the code inside the specified PanicTestFunc panics. // -// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1332,8 +1437,8 @@ func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interfa // Positive asserts that the specified element is positive // -// a.Positive(1) -// a.Positive(1.23) +// a.Positive(1) +// a.Positive(1.23) func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1343,8 +1448,8 @@ func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { // Positivef asserts that the specified element is positive // -// a.Positivef(1, "error message %s", "formatted") -// a.Positivef(1.23, "error message %s", "formatted") +// a.Positivef(1, "error message %s", "formatted") +// a.Positivef(1.23, "error message %s", "formatted") func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1354,8 +1459,8 @@ func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { // Regexp asserts that a specified regexp matches a string. // -// a.Regexp(regexp.MustCompile("start"), "it's starting") -// a.Regexp("start...$", "it's not starting") +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1365,8 +1470,8 @@ func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...inter // Regexpf asserts that a specified regexp matches a string. // -// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") -// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +// a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1376,7 +1481,7 @@ func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args . // Same asserts that two pointers reference the same object. // -// a.Same(ptr1, ptr2) +// a.Same(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1389,7 +1494,7 @@ func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs . // Samef asserts that two pointers reference the same object. // -// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// a.Samef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. @@ -1400,10 +1505,11 @@ func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, Samef(a.t, expected, actual, msg, args...) } -// Subset asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subset asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +// a.Subset([1, 2, 3], [1, 2]) +// a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1411,10 +1517,11 @@ func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ... Subset(a.t, list, subset, msgAndArgs...) } -// Subsetf asserts that the specified list(array, slice...) contains all -// elements given in the specified subset(array, slice...). +// Subsetf asserts that the specified list(array, slice...) or map contains all +// elements given in the specified subset list(array, slice...) or map. // -// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +// a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") +// a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1424,7 +1531,7 @@ func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, a // True asserts that the specified value is true. // -// a.True(myBool) +// a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1434,7 +1541,7 @@ func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { // Truef asserts that the specified value is true. // -// a.Truef(myBool, "error message %s", "formatted") +// a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1444,7 +1551,7 @@ func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { // WithinDuration asserts that the two times are within duration delta of each other. // -// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1454,7 +1561,7 @@ func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta // WithinDurationf asserts that the two times are within duration delta of each other. // -// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1464,7 +1571,7 @@ func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta // WithinRange asserts that a time is within a time range (inclusive). // -// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) +// a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() @@ -1474,7 +1581,7 @@ func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Tim // WithinRangef asserts that a time is within a time range (inclusive). // -// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") +// a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() diff --git a/vendor/github.com/stretchr/testify/suite/doc.go b/vendor/github.com/stretchr/testify/suite/doc.go index f91a245d3f..8d55a3aa89 100644 --- a/vendor/github.com/stretchr/testify/suite/doc.go +++ b/vendor/github.com/stretchr/testify/suite/doc.go @@ -29,37 +29,38 @@ // Suite object has assertion methods. // // A crude example: -// // Basic imports -// import ( -// "testing" -// "github.com/stretchr/testify/assert" -// "github.com/stretchr/testify/suite" -// ) // -// // Define the suite, and absorb the built-in basic suite -// // functionality from testify - including a T() method which -// // returns the current testing context -// type ExampleTestSuite struct { -// suite.Suite -// VariableThatShouldStartAtFive int -// } +// // Basic imports +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// "github.com/stretchr/testify/suite" +// ) // -// // Make sure that VariableThatShouldStartAtFive is set to five -// // before each test -// func (suite *ExampleTestSuite) SetupTest() { -// suite.VariableThatShouldStartAtFive = 5 -// } +// // Define the suite, and absorb the built-in basic suite +// // functionality from testify - including a T() method which +// // returns the current testing context +// type ExampleTestSuite struct { +// suite.Suite +// VariableThatShouldStartAtFive int +// } // -// // All methods that begin with "Test" are run as tests within a -// // suite. -// func (suite *ExampleTestSuite) TestExample() { -// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) -// suite.Equal(5, suite.VariableThatShouldStartAtFive) -// } +// // Make sure that VariableThatShouldStartAtFive is set to five +// // before each test +// func (suite *ExampleTestSuite) SetupTest() { +// suite.VariableThatShouldStartAtFive = 5 +// } // -// // In order for 'go test' to run this suite, we need to create -// // a normal test function and pass our suite to suite.Run -// func TestExampleTestSuite(t *testing.T) { -// suite.Run(t, new(ExampleTestSuite)) -// } +// // All methods that begin with "Test" are run as tests within a +// // suite. +// func (suite *ExampleTestSuite) TestExample() { +// assert.Equal(suite.T(), 5, suite.VariableThatShouldStartAtFive) +// suite.Equal(5, suite.VariableThatShouldStartAtFive) +// } +// +// // In order for 'go test' to run this suite, we need to create +// // a normal test function and pass our suite to suite.Run +// func TestExampleTestSuite(t *testing.T) { +// suite.Run(t, new(ExampleTestSuite)) +// } package suite diff --git a/vendor/github.com/stretchr/testify/suite/interfaces.go b/vendor/github.com/stretchr/testify/suite/interfaces.go index 8b98a8af27..fed037d7f3 100644 --- a/vendor/github.com/stretchr/testify/suite/interfaces.go +++ b/vendor/github.com/stretchr/testify/suite/interfaces.go @@ -7,6 +7,7 @@ import "testing" type TestingSuite interface { T() *testing.T SetT(*testing.T) + SetS(suite TestingSuite) } // SetupAllSuite has a SetupSuite method, which will run before the @@ -51,3 +52,15 @@ type AfterTest interface { type WithStats interface { HandleStats(suiteName string, stats *SuiteInformation) } + +// SetupSubTest has a SetupSubTest method, which will run before each +// subtest in the suite. +type SetupSubTest interface { + SetupSubTest() +} + +// TearDownSubTest has a TearDownSubTest method, which will run after +// each subtest in the suite have been run. +type TearDownSubTest interface { + TearDownSubTest() +} diff --git a/vendor/github.com/stretchr/testify/suite/suite.go b/vendor/github.com/stretchr/testify/suite/suite.go index 895591878b..18443a91c8 100644 --- a/vendor/github.com/stretchr/testify/suite/suite.go +++ b/vendor/github.com/stretchr/testify/suite/suite.go @@ -22,9 +22,13 @@ var matchMethod = flag.String("testify.m", "", "regular expression to select tes // retrieving the current *testing.T context. type Suite struct { *assert.Assertions + mu sync.RWMutex require *require.Assertions t *testing.T + + // Parent suite to have access to the implemented methods of parent struct + s TestingSuite } // T retrieves the current *testing.T context. @@ -43,12 +47,18 @@ func (suite *Suite) SetT(t *testing.T) { suite.require = require.New(t) } +// SetS needs to set the current test suite as parent +// to get access to the parent methods +func (suite *Suite) SetS(s TestingSuite) { + suite.s = s +} + // Require returns a require context for suite. func (suite *Suite) Require() *require.Assertions { suite.mu.Lock() defer suite.mu.Unlock() if suite.require == nil { - suite.require = require.New(suite.T()) + panic("'Require' must not be called before 'Run' or 'SetT'") } return suite.require } @@ -62,17 +72,19 @@ func (suite *Suite) Assert() *assert.Assertions { suite.mu.Lock() defer suite.mu.Unlock() if suite.Assertions == nil { - suite.Assertions = assert.New(suite.T()) + panic("'Assert' must not be called before 'Run' or 'SetT'") } return suite.Assertions } func recoverAndFailOnPanic(t *testing.T) { + t.Helper() r := recover() failOnPanic(t, r) } func failOnPanic(t *testing.T, r interface{}) { + t.Helper() if r != nil { t.Errorf("test panicked: %v\n%s", r, debug.Stack()) t.FailNow() @@ -85,9 +97,21 @@ func failOnPanic(t *testing.T, r interface{}) { // Provides compatibility with go test pkg -run TestSuite/TestName/SubTestName. func (suite *Suite) Run(name string, subtest func()) bool { oldT := suite.T() - defer suite.SetT(oldT) + return oldT.Run(name, func(t *testing.T) { suite.SetT(t) + defer suite.SetT(oldT) + + defer recoverAndFailOnPanic(t) + + if setupSubTest, ok := suite.s.(SetupSubTest); ok { + setupSubTest.SetupSubTest() + } + + if tearDownSubTest, ok := suite.s.(TearDownSubTest); ok { + defer tearDownSubTest.TearDownSubTest() + } + subtest() }) } @@ -98,6 +122,7 @@ func Run(t *testing.T, suite TestingSuite) { defer recoverAndFailOnPanic(t) suite.SetT(t) + suite.SetS(suite) var suiteSetupDone bool @@ -142,6 +167,8 @@ func Run(t *testing.T, suite TestingSuite) { suite.SetT(t) defer recoverAndFailOnPanic(t) defer func() { + t.Helper() + r := recover() if stats != nil { diff --git a/vendor/github.com/vmware/govmomi/.dockerignore b/vendor/github.com/vmware/govmomi/.dockerignore new file mode 100644 index 0000000000..9f5fdc6b9e --- /dev/null +++ b/vendor/github.com/vmware/govmomi/.dockerignore @@ -0,0 +1,2 @@ +Dockerfile* +.*ignore \ No newline at end of file diff --git a/vendor/github.com/vmware/govmomi/.gitignore b/vendor/github.com/vmware/govmomi/.gitignore index 9099ba3496..675d86a0ad 100644 --- a/vendor/github.com/vmware/govmomi/.gitignore +++ b/vendor/github.com/vmware/govmomi/.gitignore @@ -1,3 +1,13 @@ secrets.yml dist/ .idea/ + +# ignore tools binaries +/git-chglog + +# ignore RELEASE-specific CHANGELOG +/RELEASE_CHANGELOG.md + +# Ignore editor temp files +*~ +.vscode/ diff --git a/vendor/github.com/vmware/govmomi/.golangci.yml b/vendor/github.com/vmware/govmomi/.golangci.yml new file mode 100644 index 0000000000..25242dcaf5 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/.golangci.yml @@ -0,0 +1,19 @@ +linters: + disable-all: true + enable: + - goimports + - govet + # Run with --fast=false for more extensive checks + fast: true +# override defaults +linters-settings: + goimports: + # put imports beginning with prefix after 3rd-party packages; + # it's a comma-separated list of prefixes + local-prefixes: github.com/vmware/govmomi +run: + timeout: 6m + skip-dirs: + - vim25/json + - vim25/xml + - cns/types diff --git a/vendor/github.com/vmware/govmomi/.goreleaser.yml b/vendor/github.com/vmware/govmomi/.goreleaser.yml index a15c5d7d7c..de6ced253b 100644 --- a/vendor/github.com/vmware/govmomi/.goreleaser.yml +++ b/vendor/github.com/vmware/govmomi/.goreleaser.yml @@ -1,57 +1,166 @@ --- -project_name: govc +project_name: govmomi + builds: -- goos: - - linux - - darwin - - windows - - freebsd - goarch: - - amd64 - - 386 - env: - - CGO_ENABLED=0 - main: ./govc/main.go - binary: govc - flags: -compiler gc - ldflags: -X github.com/vmware/govmomi/govc/flags.GitVersion={{.Version}} -archive: - name_template: '{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}' - format: tar.gz - format_overrides: - - goos: windows - format: zip - files: - - none* + - id: govc + no_main_check: true + goos: &goos-defs + - linux + - darwin + - windows + - freebsd + goarch: &goarch-defs + - amd64 + - arm + - arm64 + - mips64le + - s390x + env: + - CGO_ENABLED=0 + - PKGPATH=github.com/vmware/govmomi/govc/flags + main: ./govc/main.go + binary: govc + ldflags: + - "-X {{.Env.PKGPATH}}.BuildVersion={{.Version}} -X {{.Env.PKGPATH}}.BuildCommit={{.ShortCommit}} -X {{.Env.PKGPATH}}.BuildDate={{.Date}}" + - id: vcsim + no_main_check: true + goos: *goos-defs + goarch: *goarch-defs + env: + - CGO_ENABLED=0 + main: ./vcsim/main.go + binary: vcsim + ldflags: + - "-X main.buildVersion={{.Version}} -X main.buildCommit={{.ShortCommit}} -X main.buildDate={{.Date}}" + +nfpms: + - package_name: govmomi + builds: + - govc + - vcsim + homepage: https://github.com/vmware/govmomi + maintainer: Doug MacEachern + description: |- + vSphere CLI + formats: + - rpm + +archives: + - id: govcbuild + builds: + - govc + name_template: >- + govc_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + format_overrides: &overrides + - goos: windows + format: zip + files: &extrafiles + - CHANGELOG.md + - LICENSE.txt + - README.md + + - id: vcsimbuild + builds: + - vcsim + name_template: >- + vcsim_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + format_overrides: *overrides + files: *extrafiles + +snapshot: + name_template: "{{ .Tag }}-next" + checksum: - name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' + name_template: "checksums.txt" + changelog: sort: asc filters: exclude: - - '^docs:' - - '^test:' + - "^docs:" + - "^test:" - Merge pull request - Merge branch -brew: - github: - owner: govmomi - name: homebrew-tap - commit_author: - name: Alfred the Narwhal - email: cna-alfred@vmware.com - folder: Formula - homepage: "https://github.com/vmware/govmomi/blob/master/govc/README.md" - description: "govc is a vSphere CLI built on top of govmomi." - test: | - system "#{bin}/govc version" + +# upload disabled since it is maintained in homebrew-core +brews: + - name: govc + ids: + - govcbuild + repository: + owner: govmomi + name: homebrew-tap + # TODO: create token in specified tap repo, add as secret to govmomi repo and reference in release workflow + # token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}" + # enable once we do fully automated releases + skip_upload: true + commit_author: + name: Alfred the Narwhal + email: cna-alfred@vmware.com + directory: Formula + homepage: "https://github.com/vmware/govmomi/blob/main/govc/README.md" + description: "govc is a vSphere CLI built on top of govmomi." + test: | + system "#{bin}/govc version" + install: | + bin.install "govc" + - name: vcsim + ids: + - vcsimbuild + repository: + owner: govmomi + name: homebrew-tap + # TODO: create token in specified tap repo, add as secret to govmomi repo and reference in release workflow + # token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}" + # enable once we do fully automated releases + skip_upload: true + commit_author: + name: Alfred the Narwhal + email: cna-alfred@vmware.com + directory: Formula + homepage: "https://github.com/vmware/govmomi/blob/main/vcsim/README.md" + description: "vcsim is a vSphere API simulator built on top of govmomi." + test: | + system "#{bin}/vcsim -h" + install: | + bin.install "vcsim" + dockers: - - image: vmware/govc - goos: linux - goarch: amd64 - binary: govc - tag_templates: - - "{{ .Tag }}" - - "v{{ .Major }}" - - "v{{ .Major }}.{{ .Minor }}" - - latest + - image_templates: + - "vmware/govc:{{ .Tag }}" + - "vmware/govc:{{ .ShortCommit }}" + - "vmware/govc:latest" + dockerfile: Dockerfile.govc + ids: + - govc + build_flag_templates: + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.url=https://github.com/vmware/govmomi" + - "--platform=linux/amd64" + - image_templates: + - "vmware/vcsim:{{ .Tag }}" + - "vmware/vcsim:{{ .ShortCommit }}" + - "vmware/vcsim:latest" + dockerfile: Dockerfile.vcsim + ids: + - vcsim + build_flag_templates: + - "--pull" + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.title={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.url=https://github.com/vmware/govmomi" + - "--platform=linux/amd64" diff --git a/vendor/github.com/vmware/govmomi/.mailmap b/vendor/github.com/vmware/govmomi/.mailmap index b26a72479c..dd869e10f6 100644 --- a/vendor/github.com/vmware/govmomi/.mailmap +++ b/vendor/github.com/vmware/govmomi/.mailmap @@ -1,28 +1,59 @@ +amanpaha amanpaha <84718160+amanpaha@users.noreply.github.com> +Amanda H. L. de Andrade Amanda Hager Lopes de Andrade Katz Amanda H. L. de Andrade amandahla Amit Bathla -Andrew Kutz akutz Andrew Kutz +Andrew Kutz akutz Andrew Kutz Andrew Kutz <101085+akutz@users.noreply.github.com> +Andrew Kutz akutz +Anfernee Yongkun Gui +Anfernee Yongkun Gui Yongkun Anfernee Gui +Anna Carrigan Anna +Balu Dontu BaluDontu Bruce Downs -Bruce Downs Bruce Downs +Bruce Downs +Bryan Venteicher +Brian Rak Clint Greenwood Cédric Blomart Cédric Blomart cedric David Stark +Doug MacEachern dougm +Deyan Popov <126056852+dekp@users.noreply.github.com> Eric Gray Eric Yutao eric Fabio Rapposelli +Faiyaz Ahmed Faiyaz Ahmed +Faiyaz Ahmed Faiyaz Ahmed +Faiyaz Ahmed Faiyaz Ahmed +Hakan Halil <25109775+HakanSunay@users.noreply.github.com> Henrik Hodne +Ian Eyberg Jeremy Canady +Jiatong Wang jiatongw +Kiril Karaatanassov kkaraatanassov +Kiril Karaatanassov +Lintong Jiang lintongj <55512168+lintongj@users.noreply.github.com> +Lubron Zhan lubronzhan +Lubron Zhan lubronzhan +Lubron Zhan Lubron +Michael Gasch Michael Gasch +Michael Gasch <15986659+embano1@users.noreply.github.com> +Michael Gasch embano1 +Mincho Tonev matonev <31008054+matonev@users.noreply.github.com> +Parveen Chahal Pieter Noordhuis +Ricardo Katz +Saad Malik +Stoyan Zhelyazkov <156204153+stoyanzhelyazkov@users.noreply.github.com> Takaaki Furukawa takaaki.furukawa Takaaki Furukawa tkak -Vadim Egorov -Anfernee Yongkun Gui -Anfernee Yongkun Gui Yongkun Anfernee Gui -Zach Tucker -Zee Yang -Jiatong Wang jiatongw Uwe Bessle Uwe Bessle Uwe Bessle Uwe Bessle +Vadim Egorov +William Lam +Yun Zhou <41678287+gh05tn0va@users.noreply.github.com> +Zach G zach96guan +Zach Tucker +Zee Yang diff --git a/vendor/github.com/vmware/govmomi/.travis.yml b/vendor/github.com/vmware/govmomi/.travis.yml deleted file mode 100644 index 34777d48de..0000000000 --- a/vendor/github.com/vmware/govmomi/.travis.yml +++ /dev/null @@ -1,95 +0,0 @@ -# Use the newer Travis-CI build templates based on the -# Debian Linux distribution "Trusty" release. -os: linux -dist: trusty - -# Disable sudo for all builds by default. This ensures all jobs use -# Travis-CI's containerized build environment unless specified otherwise. -# The container builds have *much* shorter queue times than the VM-based -# build environment on which the sudo builds depend. -sudo: false -services: false - -# Set the version of Go. -language: go -go: 1.11 - -# Always set the project's Go import path to ensure that forked -# builds get cloned to the correct location. -go_import_path: github.com/vmware/govmomi - -# Ensure all the jobs know where the temp directory is. -env: - global: TMPDIR=/tmp - -jobs: - include: - - # The "lint" stage runs the various linters against the project. - - &lint-stage - stage: lint - env: LINTER=govet - install: true - script: make "${LINTER}" - - - <<: *lint-stage - env: LINTER=goimports - - # The "build" stage verifies the program can be built against the - # various GOOS and GOARCH combinations found in the Go releaser - # config file, ".goreleaser.yml". - - &build-stage - stage: build - env: GOOS=linux GOARCH=amd64 - install: true - script: make install - - - <<: *build-stage - env: GOOS=linux GOARCH=386 - - - <<: *build-stage - env: GOOS=darwin GOARCH=amd64 - - <<: *build-stage - env: GOOS=darwin GOARCH=386 - - - <<: *build-stage - env: GOOS=freebsd GOARCH=amd64 - - <<: *build-stage - env: GOOS=freebsd GOARCH=386 - - - <<: *build-stage - env: GOOS=windows GOARCH=amd64 - - <<: *build-stage - env: GOOS=windows GOARCH=386 - - # The test stage executes the test target. - - stage: test - install: true - script: make test - - # The deploy stage deploys the build artifacts using goreleaser. - # - # This stage will only be activated when there is an annotated tag present - # or when the text "/ci-deploy" is present in the commit message. However, - # the "deploy" phase of the build will still only be executed on non-PR - # builds as that restriction is baked into Travis-CI. - # - # Finally, this stage requires the Travis-CI VM infrastructure in order to - # leverage Docker. This will increase the amount of time the jobs sit - # in the queue, waiting to be built. However, it's a necessity as Travis-CI - # only allows the use of Docker with VM builds. - - stage: deploy - if: tag IS present OR commit_message =~ /\/ci-deploy/ - sudo: required - services: docker - install: true - script: make install - after_success: docker login -u="${DOCKER_USERNAME}" -p="${DOCKER_PASSWORD}" - deploy: - - provider: script - skip_cleanup: true - script: curl -sL http://git.io/goreleaser | bash - addons: - apt: - update: true - packages: xmlstarlet diff --git a/vendor/github.com/vmware/govmomi/CHANGELOG.md b/vendor/github.com/vmware/govmomi/CHANGELOG.md index 97907f7969..254f540f1b 100644 --- a/vendor/github.com/vmware/govmomi/CHANGELOG.md +++ b/vendor/github.com/vmware/govmomi/CHANGELOG.md @@ -1,331 +1,4782 @@ -# changelog -### 0.20.0 (2018-02-06) + +## [Release v0.36.0](https://github.com/vmware/govmomi/compare/v0.35.0...v0.36.0) -* Add vslm package for managing First Class Disks +> Release Date: 2024-03-07 -* Add LoginByToken to session KeepAliveHandler +### 🐞 Fix -### 0.19.0 (2018-09-30) +- [fd3840e3] vcsim Fetch method causes runtime panic when property is not set +- [4254c59c] Update summary.config.hwVersion in simulator +- [44610f43] govc: use session KeepAlive in library.export command -* New vapi/rest and and vapi/tags packages +### 💫 `vcsim` (Simulator) -* Allowing the use of STS for exchanging tokens +- [c46ad1af] Enhanced sim support for upgrade VM -* Add object.VirtualMachine.UUID method +### 🧹 Chore -* SetRootCAs on the soap.Client returns an error for invalid certificates +- [ef3a3d62] Update version.go for v0.36.0 +- [01a069da] bump Go versions +- [08d2fd0b] Better support for ESXi & HW versions -* Add ClusterComputeResource.MoveInto method +### ⚠️ BREAKING -### 0.18.0 (2018-05-24) +### 📖 Commits -* Add VirtualDiskManager wrapper to set UUID +- [ef3a3d62] chore: Update version.go for v0.36.0 +- [89693ada] Updating CONTRIBUTORS +- [fd3840e3] fix: vcsim Fetch method causes runtime panic when property is not set +- [75505549] Add APIs for vLCM enablement on a cluster and base ESXi image selection +- [01a069da] chore: bump Go versions +- [7998478a] build(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0 +- [4ad8f689] Add API for vLCM - offline depots and cluster baseline images +- [08d2fd0b] chore: Better support for ESXi & HW versions +- [c46ad1af] vcsim: Enhanced sim support for upgrade VM +- [4254c59c] fix: Update summary.config.hwVersion in simulator +- [de2ce182] test fixes +- [44610f43] fix: govc: use session KeepAlive in library.export command +- [41907150] Add service locator to CNS RelocateVolume spec +- [ef555e78] Add "AggregatedSnapshotCapacityInMb" to CnsSnapshotCreateResult and CnsSnapshotDeleteResult. -* Add vmxnet2, pcnet32 and sriov to VirtualDeviceList.EthernetCardTypes + +## [Release v0.35.0](https://github.com/vmware/govmomi/compare/v0.34.2...v0.35.0) -* Add new vSphere 6.7 APIs +> Release Date: 2024-02-12 -* Decrease LoginExtensionByCertificate tunnel usage +### 💫 API Changes -* SAML token authentication support via SessionManager.LoginByToken +- [8e17e4c1] Sim vm config.changeVersion & config.modified +- [95aa2571] WaitForUpdatesEx & DestroyPropertyFilter -* New SSO admin client for managing users +### 💫 `govc` (CLI) -* New STS client for issuing and renewing SAML tokens +- [9ddfc534] json tag camelCase fixes -* New Lookup Service client for discovering endpoints such as STS and ssoadmin +### 💫 `vcsim` (Simulator) -* Switch from gvt to go dep for managing dependencies +- [557d2654] Fix -method-delay option to update task states -### 0.17.1 (2018-03-19) +### 📃 Documentation -* vcsim: add Destroy method for Folder and Datacenter types +- [2d1b52ff] update release doc -* In progress.Reader emit final report on EOF. +### 🧹 Chore -* vcsim: add EventManager.QueryEvents +- [d7c0094a] Update version.go for v0.35.0 +- [69785ff0] update CONTRIBUTORS -### 0.17.0 (2018-02-28) +### ⚠️ BREAKING -* Add HostStorageSystem.AttachScsiLun method +json tag camelCase fixes [9ddfc534]: +follow up to json tags missed in PR [#3007](https://github.com/vmware/govmomi/issues/3007) and PR [#3247](https://github.com/vmware/govmomi/issues/3247) -* Avoid possible panic in Datastore.Stat (#969) +WaitForUpdatesEx & DestroyPropertyFilter [95aa2571]: +The semantics around the helper functions in the + property package have changed. Please review any + code that calls this package to ensure it is + compatible with the new behaviors. -* Destroy event history collectors (#962) +### 📖 Commits -* Add VirtualDiskManager.CreateChildDisk method +- [d7c0094a] chore: Update version.go for v0.35.0 +- [2d1b52ff] docs: update release doc +- [69785ff0] chore: update CONTRIBUTORS +- [9ddfc534] govc: json tag camelCase fixes +- [b137a5d2] Add "AggregatedSnapshotCapacityInMb" to cnstype. +- [b948e3cb] add -json to snapshot.tree +- [dabec6cd] build(deps): bump nokogiri from 1.14.3 to 1.16.2 in /gen +- [8e17e4c1] api: Sim vm config.changeVersion & config.modified +- [d55cf6e4] build(deps): bump peter-evans/create-pull-request from 5 to 6 +- [25cab091] Re-enable PC updates for indexed properties +- [8150eedd] build(deps): bump andstor/file-existence-action from 2 to 3 +- [bfc5d64c] build(deps): bump peter-evans/create-or-update-comment from 3 to 4 +- [42d7d711] Add new "UsedCapacityInMb" in struct "CnsBlockBackingDetails" +- [61f901eb] build(deps): bump github.com/google/uuid from 1.5.0 to 1.6.0 +- [3b5917a2] build(deps): bump actions/cache from 3 to 4 +- [78898bd2] Self identify the executable making calls to vCenter +- [95aa2571] api: WaitForUpdatesEx & DestroyPropertyFilter +- [cd8a7883] Changes to fix xml tag used for SnapshotId +- [557d2654] vcsim: Fix -method-delay option to update task states +- [98b0b77f] Fixes Missing Tags in AttachedTags +- [5410a069] Changes to add CNS fault CnsSnapshotCreatedFault +- [8c1d8f18] build(deps): bump actions/upload-artifact from 3 to 4 +- [14d35380] build(deps): bump github/codeql-action from 2 to 3 +- [f6c537d7] build(deps): bump github.com/google/uuid from 1.4.0 to 1.5.0 +- [e9a9f2c0] build(deps): bump chuhlomin/render-template from 1.8 to 1.9 -### 0.16.0 (2017-11-08) + +## [Release v0.34.2](https://github.com/vmware/govmomi/compare/v0.34.1...v0.34.2) -* Add support for SOAP request operation ID header +> Release Date: 2024-01-08 -* Moved ovf helpers from govc import.ovf command to ovf and nfc packages +### 💫 `vcsim` (Simulator) -* Added guest/toolbox (client) package +- [4c8ffb26] Fix -method-delay option to update task states -* Added toolbox package and toolbox command +### 🧹 Chore -* Added simulator package and vcsim command +- [96b6eb77] Update version.go for v0.34.2 -### 0.15.0 (2017-06-19) +### ⚠️ BREAKING -* WaitOptions.MaxWaitSeconds is now optional +### 📖 Commits -* Support removal of ExtraConfig entries +- [96b6eb77] chore: Update version.go for v0.34.2 +- [4c8ffb26] vcsim: Fix -method-delay option to update task states +- [1c2c1c75] Fixes Missing Tags in AttachedTags +- [55924679] Changes to fix xml tag used for SnapshotId -* GuestPosixFileAttributes OwnerId and GroupId fields are now pointers, - rather than omitempty ints to allow chown with root uid:gid + +## [Release v0.34.1](https://github.com/vmware/govmomi/compare/v0.34.0...v0.34.1) -* Updated examples/ using view package +> Release Date: 2023-12-19 -* Add DatastoreFile.TailFunc method +### 🧹 Chore -* Export VirtualMachine.FindSnapshot method +- [754cb3aa] Update version.go for v0.34.1 -* Add AuthorizationManager {Enable,Disable}Methods +### ⚠️ BREAKING -* Add PBM client +### 📖 Commits -### 0.14.0 (2017-04-08) +- [754cb3aa] chore: Update version.go for v0.34.1 +- [dd8bbb4d] Changes to add CNS fault CnsSnapshotCreatedFault -* Add view.ContainerView type and methods + +## [Release v0.34.0](https://github.com/vmware/govmomi/compare/v0.33.1...v0.34.0) -* Add Collector.RetrieveWithFilter method +> Release Date: 2023-12-12 -* Add property.Filter type +### 🐞 Fix -* Implement EthernetCardBackingInfo for OpaqueNetwork +- [980d22d6] expose util for rest status return -* Finder: support changing object root in find mode +### 💫 API Changes -* Add VirtualDiskManager.QueryVirtualDiskInfo +- [31423b78] add object.Datastore.FindInventoryPath +- [d52f8ee3] add Content Library update session file APIs -* Add performance.Manager APIs +### 💫 `vcsim` (Simulator) -### 0.13.0 (2017-03-02) +- [4a09f19d] add PbmQueryAssociatedProfiles method +- [4cbd6424] Fix [BUG] vcsim raises TypeError for RemoveSnapshotTask +- [04ccf69e] handle HostNotConnected when saving inventory +- [2f1fefae] fix MAC Addresses to be unique +- [e19137f5] propagate VMwareDVSConfigSpec in CreateDVS_Task +- [a0923119] emit DVS and Portgroup create events +- [c8a2fc2e] Fix PropertyCollector to handle empty property -* Add DatastoreFileManager API wrapper +### 🧹 Chore -* Add HostVsanInternalSystem API wrappers +- [a5899afa] Update version.go for v0.34.0 -* Add Container support to view package +### ⚠️ BREAKING -* Finder supports Folder recursion without specifying a path +### 📖 Commits -* Add VirtualMachine.QueryConfigTarget method +- [a5899afa] chore: Update version.go for v0.34.0 +- [980d22d6] fix: expose util for rest status return +- [4a09f19d] vcsim: add PbmQueryAssociatedProfiles method +- [e39527d4] build(deps): bump actions/stale from 8 to 9 +- [4cbd6424] vcsim: Fix [BUG] vcsim raises TypeError for RemoveSnapshotTask +- [e9a782a9] build(deps): bump actions/setup-go from 4 to 5 +- [45188e1d] Add default Historical Intervals to the simulator +- [04ccf69e] vcsim: handle HostNotConnected when saving inventory +- [2f1fefae] vcsim: fix MAC Addresses to be unique +- [d32be098] simulator: fix dropped error +- [e19137f5] vcsim: propagate VMwareDVSConfigSpec in CreateDVS_Task +- [a0923119] vcsim: emit DVS and Portgroup create events +- [31423b78] api: add object.Datastore.FindInventoryPath +- [c8a2fc2e] vcsim: Fix PropertyCollector to handle empty property +- [d52f8ee3] api: add Content Library update session file APIs +- [3942d8f6] build(deps): bump github.com/google/uuid from 1.3.1 to 1.4.0 +- [09c72919] Add additional PBM methods -* Add device option to VirtualMachine.WaitForNetIP + +## [Release v0.33.1](https://github.com/vmware/govmomi/compare/v0.33.0...v0.33.1) -* Remove _Task suffix from vapp methods +> Release Date: 2023-10-30 -### 0.12.1 (2016-12-19) +### ⚠️ BREAKING -* Add DiagnosticLog helper +### 📖 Commits -* Add DatastorePath helper +- [6de69ad0] Add additional PBM methods -### 0.12.0 (2016-12-01) + +## [Release v0.33.0](https://github.com/vmware/govmomi/compare/v0.32.0...v0.33.0) -* Disable use of service ticket for datastore HTTP access by default +> Release Date: 2023-10-25 -* Attach context to HTTP requests for cancellations +### 💫 `govc` (CLI) -* Update to vim25/6.5 API +- [5264e839] add cluster.change '-ha-admission-control-enabled' flag +- [3bcaf429] add option to enable hidden properties in import.{spec,ova} -### 0.11.4 (2016-11-15) +### 💫 `vcsim` (Simulator) -* Add object.AuthorizationManager methods: RetrieveRolePermissions, RetrieveAllPermissions, AddRole, RemoveRole, UpdateRole +- [db0ba920] Handle prepare guest operations when svm is nil +- [0754d758] fix ModifyListView to return unresolved references +- [7f3a0708] Remove extra devices in OVF Deploy w/ ConfigSpec -### 0.11.3 (2016-11-08) +### 🧹 Chore -* Allow DatastoreFile.Follow reader to drain current body after stopping +- [f3c1fca9] Update version.go for v0.33.0 +- [675eebd2] remove refs to deprecated io/ioutil -### 0.11.2 (2016-11-01) +### ⚠️ BREAKING -* Avoid possible NPE in VirtualMachine.Device method +fix ModifyListView to return unresolved references [0754d758]: +api: view.ListView.{Add,Remove,Reset} methods now return unresolved references -* Add support for OpaqueNetwork type to Finder +### 📖 Commits -* Add HostConfigManager.AccountManager support for ESX 5.5 +- [f3c1fca9] chore: Update version.go for v0.33.0 +- [19726dc6] Add functionality for checking whether the provided thumbprint is known to the soap client +- [5264e839] govc: add cluster.change '-ha-admission-control-enabled' flag +- [db0ba920] vcsim: Handle prepare guest operations when svm is nil +- [0434fd26] vapi: add support for OperationID header +- [0754d758] vcsim: fix ModifyListView to return unresolved references +- [5569c012] build(deps): bump github.com/google/go-cmp from 0.5.9 to 0.6.0 +- [babee198] build(deps): bump chuhlomin/render-template from 1.7 to 1.8 +- [7f3a0708] vcsim: Remove extra devices in OVF Deploy w/ ConfigSpec +- [3bcaf429] govc: add option to enable hidden properties in import.{spec,ova} +- [675eebd2] chore: remove refs to deprecated io/ioutil -### 0.11.1 (2016-10-27) + +## [Release v0.32.0](https://github.com/vmware/govmomi/compare/v0.31.0...v0.32.0) -* Add Finder.ResourcePoolListAll method +> Release Date: 2023-09-28 -### 0.11.0 (2016-10-25) +### 🐞 Fix -* Add object.DistributedVirtualPortgroup.Reconfigure method +- [bed95133] case insensitive govc import.ova PropertyMapping -### 0.10.0 (2016-10-20) +### 💡 Examples -* Add option to set soap.Client.UserAgent +- [f2aaee58] add ListView example for waiting on updates to tasks -* Add service ticket thumbprint validation +### 💫 API Changes -* Update use of http.DefaultTransport fields to 1.7 +- [a91eb5e5] disable HTTP Keep-Alive for direct ESX connections -* Set default locale to en_US (override with GOVMOMI_LOCALE env var) +### 💫 `govc` (CLI) -* Add object.HostCertificateInfo (types.HostCertificateManagerCertificateInfo helpers) +- [db5b3d8e] camelCase json output -* Add object.HostCertificateManager type and HostConfigManager.CertificateManager method +### 💫 `vcsim` (Simulator) -* Add soap.Client SetRootCAs and SetDialTLS methods +- [524ca258] EnvironmentBrowser improvements +- [d49e401e] set HostSystem.Config.Host -### 0.9.0 (2016-09-09) +### 📃 Documentation -* Add object.DatastoreFile helpers for streaming and tailing datastore files +- [258ee244] update govc jq examples with correct case -* Add object VirtualMachine.Unregister method +### 🧹 Chore -* Add object.ListView methods: Add, Remove, Reset +- [a8d705a0] Update version.go for v0.32.0 -* Update to Go 1.7 - using stdlib's context package +### ⚠️ BREAKING -### 0.8.0 (2016-06-30) +camelCase json output [db5b3d8e]: +This change adds camelCase (lower-case 1st character) json tags for govc types -* Add session.Manager.AcquireLocalTicket +EnvironmentBrowser improvements [524ca258]: +removed object.VirtualMachine.QueryConfigTarget method +- Use object.VirtualMachine.EnvironmentBrowser().QueryConfigTarget instead -* Include StoragePod in Finder.FolderList +### 📖 Commits -* Add Finder methods for finding by ManagedObjectReference: Element, ObjectReference +- [a8d705a0] chore: Update version.go for v0.32.0 +- [f2aaee58] examples: add ListView example for waiting on updates to tasks +- [a91eb5e5] api: disable HTTP Keep-Alive for direct ESX connections +- [db5b3d8e] govc: camelCase json output +- [524ca258] vcsim: EnvironmentBrowser improvements +- [bed95133] fix: case insensitive govc import.ova PropertyMapping +- [6c19b99a] emacs: update for v0.31.0 release +- [258ee244] docs: update govc jq examples with correct case +- [d49e401e] vcsim: set HostSystem.Config.Host -* Add mo.ManagedObjectReference methods: Reference, String, FromString + +## [Release v0.31.0](https://github.com/vmware/govmomi/compare/v0.30.7...v0.31.0) -* Add support using SessionManagerGenericServiceTicket.HostName for Datastore HTTP access +> Release Date: 2023-09-25 + +### 🐞 Fix + +- [8f9e5495] govc vm.clone failure when using 'cluster' option +- [b22f730e] govc datacenter.info VM count with multiple DCs +- [65814f0c] Update some goreleaser deprecated fields +- [b4eac193] check the error chain when validating if it's x509 error +- [86cadf21] Fix the gorelease +- [1711a843] avoid modifying client transport outside of NewClient +- [313aa85b] share http.Transport with service clients +- [f81f3b36] grep warnings during generating usage documentation +- [2d11115b] support `binary` and `dateTime` in JSON +- [c4ffe464] add esxcli.Fault and revert Error() string +- [93cb079b] byte, float and int (de) serialization +- [8bc2caa1] avoid govc -verbose flag panic if an UpdateSet is nil +- [9ba1b852] include StoragePod Datastore children in ContainerView +- [8b00a93f] only limit the number of samples generated to maxSample when maxSample is greater than 0 and the number of samples to generate is greater than maxSample Closes: [#3097](https://github.com/vmware/govmomi/issues/3097) +- [4ed07633] support govc ls -xml flag +- [8554329c] Pin the result limit of ssoadmin client to its MAX + +### 💡 Examples + +- [71493efa] add rest.Client.LoginByToken +- [3bf46949] add session.Manager.LoginByToken + +### 💫 API Changes + +- [a03f4735] Fix errors w 8.0U2 GA update +- [515df5df] Update generated types to vSphere 8.0U2 GA +- [b7ceedea] Prep to update types to vSphere 8.0U2 GA +- [ccd07a01] Update generated types to vSphere 8.0U1c GA +- [4c00586f] Prep to update types to vSphere 8.0U1c GA +- [5431c33a] Type/field comments for data structures; API versions +- [4b2de289] Add SDK support for VM data sets +- [25865e57] set inventory path in SearchIndex.FindByInventoryPath +- [38d0ac0d] Add JSON transport for vim25 +- [0938fba2] Add ServerGuid to gen'd MoRef +- [e09a4128] support find.NetworkList by ID +- [e8fa981e] support find.Network by cluster path +- [4e6d6424] JSON Discriminators for vim25/types +- [99200868] Generate JSON tags + +### 💫 `govc` (CLI) + +- [c4d851b2] Add CLI support for VM data sets +- [02f353dd] Command to print device/backings model as tree +- [af7833bb] Fix memory aliasing in for loop (gosec G601) +- [e17d8842] add -file flag for cluster.module.rm +- [e34c7218] Add CLI device protocol support for vm.network.add +- [48bdfada] Add --help +- [28014f9b] Add general usage message +- [e5f3cd0b] add detail error message for host.esxcli commands +- [81733d0e] add cluster.mv command +- [daaaca0f] Add support for CNS volume snapshots +- [477bf69b] Support JSON protocol using environment variable +- [b8007c4b] dont check poweredOn for vm.console vmrc requests +- [6b34770c] add sso.idp.ldap.update command +- [e5b2aa37] Add feature VM IOMMU enablement support +- [f4c678ad] Add checksum validation to govc import.ova +- [e935b5a8] Add feature to get and set default idp + +### 💫 `vcsim` (Simulator) + +- [35ec7c3f] Add simulator support for VM data sets +- [c77de71c] Introduce separation btw new service instance & infra creation +- [2b5c457e] add interactive debug github action stage +- [9b2ef986] use docker event for efficient monitoring +- [6f34f131] container backing respects changes via reconfigure +- [6248cbfe] create underlay network for pNICs in container-backed hosts +- [6b7b0dfc] per-host OptionManager instances and differentiated roles +- [387dc6e5] support container backing for hosts +- [fdb4d847] untangle container/VM to allow reuse of container logic for hosts +- [9d8380ce] Fix RefreshDatastore to return a valid response +- [47dd6e02] add PerformanceManager counter values +- [65b6c51f] add lookup.EndpointURL tests +- [cd9446c7] apply PCI UnitNumber offset of 7 for ethernet +- [11356057] set StandbyMode default to "none" +- [0a351a84] Add RUN.env flag to inject environment variables to container-backed VM +- [112777b8] Fix VM ExtraConfig +- [e6217900] make task lock handoff optional +- [6c0ed53b] async guest shutdown and standby +- [297c79bf] add VirtualMachine.StandbyGuest support +- [7a04bd00] Fix FindByInventoryPath to handle root folder +- [78a979c9] Add CSV format support to QueryPerf API +- [c62983fd] add ssoadmin user and group management +- [eb9c11c6] add guest.net.ipConfig + +### 📃 Documentation + +- [e4a36881] Add README to vendored JSON pkg + +### 🧹 Chore + +- [2fab8d53] Update version.go for v0.31.0 +- [c460f706] Dockerfile & steps for generating types +- [7e490563] add missing guest OS IDs +- [0ed91a21] bump embano1/wip +- [c6005086] Err on json.Decode for invalid type/vals +- [2f5d7c62] fix WaitForUpdates bats test race +- [03718c0f] remove sso bats test hacks +- [4aad418a] upgrade to bats-core v1.9.0 release +- [d1af63ff] fix jq query case +- [91f51cfb] sync httptest/server race fix +- [80e6b73f] add timeout to bats tests +- [3158766f] adjust cert trust checks to support newer Go versions +- [4153cba9] Update CI to Go 1.20 +- [5b3da2e4] upgrade golangci-lint +- [825c73c2] bats related fixes +- [1991de51] Remove JSON tag for "This" / ArrayOf "_value" +- [b594bf1f] Move to main +- [e639aba1] Exclude vim25/json from CodeStyle workflow +- [908aa065] Include LICENSE in vendored JSON pkg +- [5caa20a4] JSON Encoding w Discriminator Support +- [a581fd01] Vendor Go 1.17.13 encoding/json + +### ⚠️ BREAKING + + [4f9f126a]: +change string to *string for Item.Description and Library.Description in package library + +Testing done: +- Test against a VC testbed +Sending a UpdateLibraryItem request with this change, and set the new description to "". +The original item description was "virtualmachinepublishrequest.vmware.com: 6b0d06ad-8e18-4881-a806-2a7c8a7e1b4b", +after this UpdateLibraryItem request succeeded, the item description was set to "". +While before this change, it would be a no-op for the description. +- Test using govc + - Update Library +``` +Create a library: +➜ govmomi git:(issue-3048) ✗ govc library.create -d "description-1" cl-1 +495f611a-cf74-40d6-a54a-8b239cf15406 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info 495f611a-cf74-40d6-a54a-8b239cf15406 +Name: cl-1 + ID: 495f611a-cf74-40d6-a54a-8b239cf15406 + Path: /cl-1 + Description: description-1 + Version: 2 + Created: Fri Feb 17 19:18:22 2023 + Security Policy ID + StorageBackings: + DatastoreID: sharedVmfs-0 + Type: DATASTORE + +Update the library description with new string: +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -d "new description" 495f611a-cf74-40d6-a54a-8b239cf15406 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info 495f611a-cf74-40d6-a54a-8b239cf15406 +Name: cl-1 + ID: 495f611a-cf74-40d6-a54a-8b239cf15406 + Path: /cl-1 + Description: new description + Version: 3 + Created: Fri Feb 17 19:18:22 2023 + Security Policy ID + StorageBackings: + DatastoreID: sharedVmfs-0 + Type: DATASTORE + +Update the item name, description is not erased. +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -n "cl-1-new" 495f611a-cf74-40d6-a54a-8b239cf15406 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info 495f611a-cf74-40d6-a54a-8b239cf15406 +Name: cl-1-new + ID: 495f611a-cf74-40d6-a54a-8b239cf15406 + Path: /cl-1-new + Description: new description + Version: 4 + Created: Fri Feb 17 19:18:22 2023 + Security Policy ID + StorageBackings: + DatastoreID: sharedVmfs-0 + Type: DATASTORE + +Update the library description with empty string: +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -d "" +495f611a-cf74-40d6-a54a-8b239cf15406 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info 495f611a-cf74-40d6-a54a-8b239cf15406 +Name: cl-1-new + ID: 495f611a-cf74-40d6-a54a-8b239cf15406 + Path: /cl-1-new + Description: + Version: 5 + Created: Fri Feb 17 19:18:22 2023 + Security Policy ID + StorageBackings: + DatastoreID: sharedVmfs-0 + Type: DATASTORE +``` + - Update Library Item +``` +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -d "item-2" /cl-1/image-2 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info /cl-1/image-2 +Name: image-2 + ID: 0dc7df56-31e0-47dc-8b0a-6a33279ddccc + Path: /cl-1/image-2 + Description: item-2 + Type: ovf + Size: 2.0GB + Created: Wed Feb 15 23:05:15 2023 + Modified: Fri Feb 17 19:29:54 2023 + Version: 3 + Security Compliance: true + Certificate Status: INTERNAL + +Update item name: +govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -n "image-2-new" /cl-1/image-2 +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info /cl-1/image-2-new +Name: image-2-new + ID: 0dc7df56-31e0-47dc-8b0a-6a33279ddccc + Path: /cl-1/image-2-new + Description: item-2 + Type: ovf + Size: 2.0GB + Created: Wed Feb 15 23:05:15 2023 + Modified: Fri Feb 17 19:31:44 2023 + Version: 4 + Security Compliance: true + Certificate Status: INTERNAL + +Update item description to empty string +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.update -d "" /cl-1/image-2-new +➜ govmomi git:(issue-3048) ✗ ~/go/bin/govc library.info /cl-1/image-2-new +Name: image-2-new + ID: 0dc7df56-31e0-47dc-8b0a-6a33279ddccc + Path: /cl-1/image-2-new + Description: + Type: ovf + Size: 2.0GB + Created: Wed Feb 15 23:05:15 2023 + Modified: Fri Feb 17 19:32:56 2023 + Version: 5 + Security Compliance: true + Certificate Status: INTERNAL +``` + +Move to main [b594bf1f]: +Changing GoVmomi's default branch from `master` to `main` will likely result +in dependents needing to repoint their clients and other integrations to +the new, default branch. + +Generate JSON tags [99200868]: +Updating the `vim25/types` with camelCased, JSON tags affects +the output of the `govc` command when using the `-json` flag +to emit results as JSON. Field names that used to be PascalCased +will now be camelCased. Queries for tools that parse JSON, such +as `jq`, will need to be updated to use the new camelCased fields. + +### 📖 Commits + +- [2fab8d53] chore: Update version.go for v0.31.0 +- [a03f4735] api: Fix errors w 8.0U2 GA update +- [515df5df] api: Update generated types to vSphere 8.0U2 GA +- [b7ceedea] api: Prep to update types to vSphere 8.0U2 GA +- [3fb5b821] Use Envoy sidecar for guest and datastore file transfer. +- [ccd07a01] api: Update generated types to vSphere 8.0U1c GA +- [4c00586f] api: Prep to update types to vSphere 8.0U1c GA +- [5431c33a] api: Type/field comments for data structures; API versions +- [c4d851b2] govc: Add CLI support for VM data sets +- [35ec7c3f] vcsim: Add simulator support for VM data sets +- [4b2de289] api: Add SDK support for VM data sets +- [02f353dd] govc: Command to print device/backings model as tree +- [8f9e5495] fix: govc vm.clone failure when using 'cluster' option +- [db076152] build(deps): bump goreleaser/goreleaser-action from 4 to 5 +- [00407ce9] build(deps): bump actions/checkout from 3 to 4 +- [c77de71c] vcsim: Introduce separation btw new service instance & infra creation +- [b22f730e] fix: govc datacenter.info VM count with multiple DCs +- [af7833bb] govc: Fix memory aliasing in for loop (gosec G601) +- [73b4535e] build(deps): bump github.com/google/uuid from 1.3.0 to 1.3.1 +- [e6bb6ce2] govc/library: fix dropped error +- [e17d8842] govc: add -file flag for cluster.module.rm +- [f636e960] Address review comments +- [2b5c457e] vcsim: add interactive debug github action stage +- [9b2ef986] vcsim: use docker event for efficient monitoring +- [6f34f131] vcsim: container backing respects changes via reconfigure +- [6248cbfe] vcsim: create underlay network for pNICs in container-backed hosts +- [6b7b0dfc] vcsim: per-host OptionManager instances and differentiated roles +- [387dc6e5] vcsim: support container backing for hosts +- [fdb4d847] vcsim: untangle container/VM to allow reuse of container logic for hosts +- [40264da9] Trim leading slash on soap path +- [9d8380ce] vcsim: Fix RefreshDatastore to return a valid response +- [47dd6e02] vcsim: add PerformanceManager counter values +- [c6a9ac8f] Bypass lookup svc for STS and SSOadmin clients +- [ddfd7eb0] remove bad spacing in new pull request template +- [65b6c51f] vcsim: add lookup.EndpointURL tests +- [c460f706] chore: Dockerfile & steps for generating types +- [4cf0b760] Allow picking datastore upload URL scheme by env +- [319e4723] build: quote golang version in release file to workaround issue in github action Close [#3179](https://github.com/vmware/govmomi/issues/3179) +- [65814f0c] fix: Update some goreleaser deprecated fields +- [b4eac193] fix: check the error chain when validating if it's x509 error +- [cd9446c7] vcsim: apply PCI UnitNumber offset of 7 for ethernet +- [3322f61b] Merge branch 'main' of github.com:vmware/govmomi into notable-user-otel-contrib +- [e34c7218] govc: Add CLI device protocol support for vm.network.add +- [eebdbefc] add opentelemetry collector contrib as notable user +- [86cadf21] fix: Fix the gorelease +- [1711a843] fix: avoid modifying client transport outside of NewClient +- [313aa85b] fix: share http.Transport with service clients +- [d648a215] add cnssyncdatastore API +- [5c7bf5f8] Remove client request log from debug tracing +- [11356057] vcsim: set StandbyMode default to "none" +- [48bdfada] govc: Add --help +- [f81f3b36] fix: grep warnings during generating usage documentation +- [28014f9b] govc: Add general usage message +- [0a351a84] vcsim: Add RUN.env flag to inject environment variables to container-backed VM +- [112777b8] vcsim: Fix VM ExtraConfig +- [e6217900] vcsim: make task lock handoff optional +- [6c0ed53b] vcsim: async guest shutdown and standby +- [7e490563] chore: add missing guest OS IDs +- [297c79bf] vcsim: add VirtualMachine.StandbyGuest support +- [833cf28e] build(deps): bump github.com/stretchr/testify from 1.8.3 to 1.8.4 +- [2d11115b] fix: support `binary` and `dateTime` in JSON +- [2731f2d5] Rm SetIndent in json.NewEncoder / JSON file name +- [0ed91a21] chore: bump embano1/wip +- [c4ffe464] fix: add esxcli.Fault and revert Error() string +- [174fb998] build(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.3 +- [e5f3cd0b] govc: add detail error message for host.esxcli commands +- [c65a8461] build(deps): bump chuhlomin/render-template from 1.6 to 1.7 +- [93cb079b] fix: byte, float and int (de) serialization +- [7a04bd00] vcsim: Fix FindByInventoryPath to handle root folder +- [81733d0e] govc: add cluster.mv command +- [685bd768] Add RUN.port.xx flag to publish ports on container backed VM +- [8bc2caa1] fix: avoid govc -verbose flag panic if an UpdateSet is nil +- [78a979c9] vcsim: Add CSV format support to QueryPerf API +- [9ba1b852] fix: include StoragePod Datastore children in ContainerView +- [8b00a93f] fix: only limit the number of samples generated to maxSample when maxSample is greater than 0 and the number of samples to generate is greater than maxSample Closes: [#3097](https://github.com/vmware/govmomi/issues/3097) +- [25865e57] api: set inventory path in SearchIndex.FindByInventoryPath +- [c6005086] chore: Err on json.Decode for invalid type/vals +- [5a2fa4fd] build(deps): bump nokogiri from 1.13.10 to 1.14.3 in /gen +- [4ed5b077] Make mounting DMI information optional with docker-backed vcsim +- [a1c8c4c8] build(deps): bump peter-evans/create-pull-request from 4 to 5 +- [8bcff40b] build(deps): bump peter-evans/create-or-update-comment from 2 to 3 +- [daaaca0f] govc: Add support for CNS volume snapshots +- [bf0510b1] build(deps): bump github.com/google/go-cmp from 0.5.7 to 0.5.9 +- [477bf69b] govc: Support JSON protocol using environment variable +- [38d0ac0d] api: Add JSON transport for vim25 +- [4ed07633] fix: support govc ls -xml flag +- [2f5d7c62] chore: fix WaitForUpdates bats test race +- [03718c0f] chore: remove sso bats test hacks +- [4aad418a] chore: upgrade to bats-core v1.9.0 release +- [d1af63ff] chore: fix jq query case +- [91f51cfb] chore: sync httptest/server race fix +- [80e6b73f] chore: add timeout to bats tests +- [49f82b8e] build(deps): bump actions/stale from 7 to 8 +- [b8007c4b] govc: dont check poweredOn for vm.console vmrc requests +- [0938fba2] api: Add ServerGuid to gen'd MoRef +- [71493efa] examples: add rest.Client.LoginByToken +- [3bf46949] examples: add session.Manager.LoginByToken +- [c62983fd] vcsim: add ssoadmin user and group management +- [3158766f] chore: adjust cert trust checks to support newer Go versions +- [4153cba9] chore: Update CI to Go 1.20 +- [5b3da2e4] chore: upgrade golangci-lint +- [b3a9e0c6] build(deps): bump actions/setup-go from 3 to 4 +- [6b34770c] govc: add sso.idp.ldap.update command +- [e5b2aa37] govc: Add feature VM IOMMU enablement support +- [1ea4b002] build(deps): bump golang.org/x/text from 0.3.7 to 0.3.8 in /hack/tools +- [4f9f126a] Use string pointer for library/item description field. +- [e09a4128] api: support find.NetworkList by ID +- [e8fa981e] api: support find.Network by cluster path +- [ea058454] lookup.EndpointURL should only save thumbprints for endpoints outside of vCenter +- [eb9c11c6] vcsim: add guest.net.ipConfig +- [825c73c2] chore: bats related fixes +- [f4c678ad] govc: Add checksum validation to govc import.ova +- [1991de51] chore: Remove JSON tag for "This" / ArrayOf "_value" +- [e935b5a8] govc: Add feature to get and set default idp +- [1970ec36] build(deps): bump actions/stale from 6 to 7 +- [8554329c] fix: Pin the result limit of ssoadmin client to its MAX +- [b594bf1f] chore: Move to main +- [4e6d6424] api: JSON Discriminators for vim25/types +- [99200868] api: Generate JSON tags +- [e639aba1] chore: Exclude vim25/json from CodeStyle workflow +- [e4a36881] docs: Add README to vendored JSON pkg +- [908aa065] chore: Include LICENSE in vendored JSON pkg +- [5caa20a4] chore: JSON Encoding w Discriminator Support +- [dc1a57ec] build(deps): bump goreleaser/goreleaser-action from 3 to 4 +- [a581fd01] chore: Vendor Go 1.17.13 encoding/json +- [9bd958aa] build(deps): bump nokogiri from 1.13.9 to 1.13.10 in /gen + + +## [Release v0.30.7](https://github.com/vmware/govmomi/compare/v0.30.6...v0.30.7) + +> Release Date: 2023-08-04 + +### 🐞 Fix + +- [cd0c259a] Update some goreleaser deprecated fields + +### 💫 `vcsim` (Simulator) + +- [3dac2e7d] Fix RefreshDatastore to return a valid response +- [fe7a0ac2] add PerformanceManager counter values + +### 🧹 Chore + +- [46fd9d2d] Update version.go for v0.30.7 + +### ⚠️ BREAKING + +### 📖 Commits + +- [46fd9d2d] chore: Update version.go for v0.30.7 +- [3dac2e7d] vcsim: Fix RefreshDatastore to return a valid response +- [fe7a0ac2] vcsim: add PerformanceManager counter values +- [552dfab2] build: quote golang version in release file to workaround issue in github action Close [#3179](https://github.com/vmware/govmomi/issues/3179) +- [cd0c259a] fix: Update some goreleaser deprecated fields + + +## [Release v0.30.6](https://github.com/vmware/govmomi/compare/v0.30.5...v0.30.6) + +> Release Date: 2023-07-17 + +### 🐞 Fix + +- [ad995d4e] check the error chain when validating if it's x509 error +- [0a77c755] Fix the gorelease + +### 💫 `govc` (CLI) + +- [4df1b85b] Add CLI device protocol support for vm.network.add -### 0.7.1 (2016-06-03) +### 🧹 Chore -* Fix object.ObjectName method +- [55614148] Update version.go for v0.30.6 +- [1079be90] adjust cert trust checks to support newer Go versions +- [64aafeb9] Update CI to Go 1.20 -### 0.7.0 (2016-06-02) +### ⚠️ BREAKING -* Move InventoryPath field to object.Common +### 📖 Commits -* Add HostDatastoreSystem.CreateLocalDatastore method +- [55614148] chore: Update version.go for v0.30.6 +- [ad995d4e] fix: check the error chain when validating if it's x509 error +- [1079be90] chore: adjust cert trust checks to support newer Go versions +- [0a77c755] fix: Fix the gorelease +- [4df1b85b] govc: Add CLI device protocol support for vm.network.add +- [64aafeb9] chore: Update CI to Go 1.20 -* Add DatastoreNamespaceManager methods: CreateDirectory, DeleteDirectory + +## [Release v0.30.5](https://github.com/vmware/govmomi/compare/v0.30.4...v0.30.5) -* Add HostServiceSystem +> Release Date: 2023-06-27 -* Add HostStorageSystem methods: MarkAsSdd, MarkAsNonSdd, MarkAsLocal, MarkAsNonLocal +### 🐞 Fix -* Add HostStorageSystem.RescanAllHba method +- [03aa9dca] avoid govc -verbose flag panic if an UpdateSet is nil +- [b366e940] include StoragePod Datastore children in ContainerView +- [ae6efc9f] only limit the number of samples generated to maxSample when maxSample is greater than 0 and the number of samples to generate is greater than maxSample Closes: [#3097](https://github.com/vmware/govmomi/issues/3097) +- [b1290083] support govc ls -xml flag -### 0.6.2 (2016-05-11) +### 💡 Examples -* Get complete file details in Datastore.Stat +- [46bf2408] add rest.Client.LoginByToken +- [d4e31429] add session.Manager.LoginByToken -* SOAP decoding fixes +### 💫 API Changes -* Add VirtualMachine.RemoveAllSnapshot +- [afd45d68] set inventory path in SearchIndex.FindByInventoryPath -### 0.6.1 (2016-04-30) +### 💫 `govc` (CLI) -* Fix mo.Entity interface +- [ecca4141] dont check poweredOn for vm.console vmrc requests -### 0.6.0 (2016-04-29) +### 💫 `vcsim` (Simulator) -* Add Common.Rename method +- [844274fd] set StandbyMode default to "none" +- [a405207d] Add RUN.env flag to inject environment variables to container-backed VM +- [3466b11d] Fix FindByInventoryPath to handle root folder +- [04737364] Add CSV format support to QueryPerf API +- [d46fe80a] add ssoadmin user and group management -* Add mo.Entity interface +### 🧹 Chore -* Add OptionManager +- [5373c143] Update version.go for v0.30.5 +- [e2f14cd9] add missing guest OS IDs -* Add Finder.FolderList method +### ⚠️ BREAKING -* Add VirtualMachine.WaitForNetIP method +### 📖 Commits -* Add VirtualMachine.RevertToSnapshot method +- [5373c143] chore: Update version.go for v0.30.5 +- [844274fd] vcsim: set StandbyMode default to "none" +- [a405207d] vcsim: Add RUN.env flag to inject environment variables to container-backed VM +- [e2f14cd9] chore: add missing guest OS IDs +- [3466b11d] vcsim: Fix FindByInventoryPath to handle root folder +- [3afdbf25] Add RUN.port.xx flag to publish ports on container backed VM +- [03aa9dca] fix: avoid govc -verbose flag panic if an UpdateSet is nil +- [04737364] vcsim: Add CSV format support to QueryPerf API +- [b366e940] fix: include StoragePod Datastore children in ContainerView +- [ae6efc9f] fix: only limit the number of samples generated to maxSample when maxSample is greater than 0 and the number of samples to generate is greater than maxSample Closes: [#3097](https://github.com/vmware/govmomi/issues/3097) +- [afd45d68] api: set inventory path in SearchIndex.FindByInventoryPath +- [16a58c2f] Make mounting DMI information optional with docker-backed vcsim +- [b1290083] fix: support govc ls -xml flag +- [ecca4141] govc: dont check poweredOn for vm.console vmrc requests +- [46bf2408] examples: add rest.Client.LoginByToken +- [d4e31429] examples: add session.Manager.LoginByToken +- [d46fe80a] vcsim: add ssoadmin user and group management -* Add Datastore.Download method + +## [Release v0.30.4](https://github.com/vmware/govmomi/compare/v0.30.3...v0.30.4) -### 0.5.0 (2016-03-30) +> Release Date: 2023-03-16 -Generated fields using xsd type 'int' change to Go type 'int32' +### 💫 API Changes -VirtualDevice.UnitNumber field changed to pointer type +- [23a6824e] support find.Network by cluster path +- [f4f6a5a7] support find.NetworkList by ID -### 0.4.0 (2016-02-26) +### 💫 `govc` (CLI) -* Add method to convert virtual device list to array with virtual device - changes that can be used in the VirtualMachineConfigSpec. +- [52328902] Add feature VM IOMMU enablement support -* Make datastore cluster traversable in lister +### 🧹 Chore -* Add finder.DatastoreCluster methods (also known as storage pods) +- [4561966a] Update version.go for v0.30.4 -* Add Drone CI check +### ⚠️ BREAKING -* Add object.Datastore Type and AttachedClusterHosts methods +### 📖 Commits -* Add finder.*OrDefault methods +- [4561966a] chore: Update version.go for v0.30.4 +- [52328902] govc: Add feature VM IOMMU enablement support +- [23a6824e] api: support find.Network by cluster path +- [f4f6a5a7] api: support find.NetworkList by ID -### 0.3.0 (2016-01-16) + +## [Release v0.30.3](https://github.com/vmware/govmomi/compare/v0.30.2...v0.30.3) -* Add object.VirtualNicManager wrapper +> Release Date: 2023-03-16 -* Add object.HostVsanSystem wrapper +### 🧹 Chore -* Add object.HostSystem methods: EnterMaintenanceMode, ExitMaintenanceMode, Disconnect, Reconnect +- [0d36cdc9] Update version.go for v0.30.3 -* Add finder.Folder method +### ⚠️ BREAKING -* Add object.Common.Destroy method +### 📖 Commits -* Add object.ComputeResource.Reconfigure method +- [0d36cdc9] chore: Update version.go for v0.30.3 -* Add license.AssignmentManager wrapper + +## [Release v0.30.2](https://github.com/vmware/govmomi/compare/v0.30.1...v0.30.2) -* Add object.HostFirewallSystem wrapper +> Release Date: 2023-02-01 -* Add object.DiagnosticManager wrapper +### 🐞 Fix -* Add LoginExtensionByCertificate support +- [4136fd8e] Pin the result limit of ssoadmin client to its MAX -* Add object.ExtensionManager +### 💫 `vcsim` (Simulator) -... +- [997d9ddc] add guest.net.ipConfig -### 0.2.0 (2015-09-15) +### 🧹 Chore -* Update to vim25/6.0 API +- [9078b0b4] Update version.go for v0.30.2 -* Stop returning children from `ManagedObjectList` +### ⚠️ BREAKING - Change the `ManagedObjectList` function in the `find` package to only - return the managed objects specified by the path argument and not their - children. The original behavior was used by govc's `ls` command and is - now available in the newly added function `ManagedObjectListChildren`. +### 📖 Commits -* Add retry functionality to vim25 package +- [9078b0b4] chore: Update version.go for v0.30.2 +- [997d9ddc] vcsim: add guest.net.ipConfig +- [4136fd8e] fix: Pin the result limit of ssoadmin client to its MAX -* Change finder functions to no longer take varargs + +## [Release v0.30.1](https://github.com/vmware/govmomi/compare/v0.30.0...v0.30.1) - The `find` package had functions to return a list of objects, given a - variable number of patterns. This makes it impossible to distinguish which - patterns produced results and which ones didn't. +> Release Date: 2023-01-28 - In particular for govc, where multiple arguments can be passed from the - command line, it is useful to let the user know which ones produce results - and which ones don't. +### 🧹 Chore - To evaluate multiple patterns, the user should call the find functions - multiple times (either serially or in parallel). +- [76a194ea] Update version.go for v0.30.1 -* Make optional boolean fields pointers (`vim25/types`). +### ⚠️ BREAKING - False is the zero value of a boolean field, which means they are not serialized - if the field is marked "omitempty". If the field is a pointer instead, the zero - value will be the nil pointer, and both true and false values are serialized. +### 📖 Commits -### 0.1.0 (2015-03-17) +- [76a194ea] chore: Update version.go for v0.30.1 +- [5818061a] build(deps): bump goreleaser/goreleaser-action from 3 to 4 +- [fee275a6] lookup.EndpointURL should only save thumbprints for endpoints outside of vCenter -Prior to this version the API of this library was in flux. + +## [Release v0.30.0](https://github.com/vmware/govmomi/compare/v0.29.0...v0.30.0) -Notable changes w.r.t. the state of this library before March 2015 are: +> Release Date: 2022-12-12 -* All functions that may execute a request take a `context.Context` parameter. -* The `vim25` package contains a minimal client implementation. -* The property collector and its convenience functions live in the `property` package. +### 🐞 Fix + +- [1ad33d48] Heal the broken Namespace API +- [22c48147] Update $mktemp to support macOS +- [05b0b08c] DialTLSContext / Go 1.18+ CertificateVerify support + +### 💫 API Changes + +- [58f4112b] Update types to vSphere 8.0 GA +- [ba206c5b] add Content Library security compliance support +- [4c24f821] Add SRIOV device names +- [642156dd] Adds vSphere 7.0u1-u3 support to namespace-management (Tanzu) + +### 💫 `govc` (CLI) + +- [60a18c56] about.cert was not respecting -k +- [15d1181d] bash completion improvements +- [0dbf717b] Add sso.lpp.info and sso.lpp.update commands +- [fe87cff9] host.info: use writer instead of os.stdout +- [a7196e41] host.info: use writer instead of os.stdout +- [3d6de9da] fix host.esxcli runtime error occurred when no arguments specified +- [8c7ba5ef] Add feature in sso.group.ls to list groups using FindGroupsInGroup method +- [dc3e1d79] Add feature sso.group.lsgroups using FindGroupsInGroup method +- [bf991e6e] add event key for json and plain text output +- [2017e846] Support creating content libraries with security policies + +### 💫 `vcsim` (Simulator) + +- [86f9d42a] Update test keys to be RSA 2048 +- [cedf695b] Fix duplicated name check in CloneVM_Task +- [8f4da558] add QueryNetworkHint support for LLDP and CDP details +- [1cab3254] Fix RetrieveProperties path validation to avoid panic +- [7f42a1d2] use node id for ServiceContent.InstanceUuid +- [03319493] Fix snapshot tasks to update rootSnapshot +- [b6ebcb6b] Fix disk capacity validation in ConfigureDevices +- [61032a23] Fix StorageIOAllocationInfo of VirtualDisk +- [cbfe0c93] support disconnect/reconnect host +- [b44828a4] Fix datastore freespace changed by ReconfigVM_Task + +### 📃 Documentation + +- [813a5d88] update `README.md` + +### 🧹 Chore + +- [eabc29ba] Update version.go for v0.30.0 + +### ⚠️ BREAKING + +### 📖 Commits + +- [eabc29ba] chore: Update version.go for v0.30.0 +- [1c919824] Update CONTRIBUTORS for release +- [1ad33d48] fix: Heal the broken Namespace API +- [22c48147] fix: Update $mktemp to support macOS +- [05b0b08c] fix: DialTLSContext / Go 1.18+ CertificateVerify support +- [86f9d42a] vcsim: Update test keys to be RSA 2048 +- [60a18c56] govc: about.cert was not respecting -k +- [58f4112b] api: Update types to vSphere 8.0 GA +- [15d1181d] govc: bash completion improvements +- [c018f078] perms on template files +- [813a5d88] docs: update `README.md` +- [0dbf717b] govc: Add sso.lpp.info and sso.lpp.update commands +- [fe87cff9] govc: host.info: use writer instead of os.stdout +- [a7196e41] govc: host.info: use writer instead of os.stdout +- [ba206c5b] api: add Content Library security compliance support +- [cedf695b] vcsim: Fix duplicated name check in CloneVM_Task +- [8f4da558] vcsim: add QueryNetworkHint support for LLDP and CDP details +- [3b2816ac] Add optional recommRequired PlaceVmsXCluster req arguments +- [f975908a] build(deps): bump andstor/file-existence-action from 1 to 2 +- [1373b80f] build(deps): bump chuhlomin/render-template from 1.5 to 1.6 +- [dc55a27e] build(deps): bump nokogiri from 1.13.6 to 1.13.9 in /gen +- [63980ff2] Fix: use latestPages in task HistoryCollector +- [3d6de9da] govc: fix host.esxcli runtime error occurred when no arguments specified +- [1e9eed94] Update list of projects using govmomi +- [7f4d115c] fixup! api: Add SRIOV device names +- [8f1dc575] Add API cnsreconfigpolicy bindings and static check fixes to cns/client_test.go +- [bf68e8f0] fixup! api: Add SRIOV device names +- [4c24f821] api: Add SRIOV device names +- [c1bb56db] Updated USAGE.md +- [aca677ad] build(deps): bump actions/stale from 5 to 6 +- [1cab3254] vcsim: Fix RetrieveProperties path validation to avoid panic +- [65a6f6bc] Address review comments +- [99d12605] correct new lines in group.ls +- [4d9f6e01] correct new lines in USAGE.md +- [e5bee862] move FindUsersInGroup to users.ls +- [8c7ba5ef] govc: Add feature in sso.group.ls to list groups using FindGroupsInGroup method +- [ee332ae7] Add new query selection parameters to be used for QueryAllVolume/QueryVolumeAsync API +- [dc3e1d79] govc: Add feature sso.group.lsgroups using FindGroupsInGroup method +- [201ae28f] Add common stub for hgfs for non-linux env +- [7f42a1d2] vcsim: use node id for ServiceContent.InstanceUuid +- [76e99b00] Boilerplate check requires a date range in the license. +- [bf991e6e] govc: add event key for json and plain text output +- [4a29caee] add OpenBSD build constraint +- [81bc76bc] toolbbox: add hgfs OpenBSD stub +- [03319493] vcsim: Fix snapshot tasks to update rootSnapshot +- [b6ebcb6b] vcsim: Fix disk capacity validation in ConfigureDevices +- [2017e846] govc: Support creating content libraries with security policies +- [642156dd] api: Adds vSphere 7.0u1-u3 support to namespace-management (Tanzu) +- [61032a23] vcsim: Fix StorageIOAllocationInfo of VirtualDisk +- [cbfe0c93] vcsim: support disconnect/reconnect host +- [b44828a4] vcsim: Fix datastore freespace changed by ReconfigVM_Task + + +## [Release v0.29.0](https://github.com/vmware/govmomi/compare/v0.28.5...v0.29.0) + +> Release Date: 2022-07-06 + +### 🐞 Fix + +- [d6dd8fb3] Typos in vim25/soap/client CA tests +- [e086dfe4] generate negative device key in AssignController +- [37b3b24c] avoid possible panic in govc metric commands + +### 💫 API Changes + +- [e6b5974a] Add versioned user-agent header + +### 💫 `vcsim` (Simulator) + +- [a1a36c9a] Fix disk capacity fields in ReconfigVM_Task +- [361c90ca] Remove VM Guest.Net entry when removing Ethernet card + +### 📃 Documentation + +- [5f5fb51e] Fix broken link in PR template + +### 🧹 Chore + +- [69ac8494] Update version.go for v0.29.0 +- [80489cb5] Update release automation + +### ⚠️ BREAKING + +### 📖 Commits + +- [69ac8494] chore: Update version.go for v0.29.0 +- [7d3b2b39] Update generated types +- [a1a36c9a] vcsim: Fix disk capacity fields in ReconfigVM_Task +- [5f5fb51e] docs: Fix broken link in PR template +- [d6dd8fb3] fix: Typos in vim25/soap/client CA tests +- [e086dfe4] fix: generate negative device key in AssignController +- [361c90ca] vcsim: Remove VM Guest.Net entry when removing Ethernet card +- [80489cb5] chore: Update release automation +- [e6b5974a] api: Add versioned user-agent header +- [37b3b24c] fix: avoid possible panic in govc metric commands + + +## [Release v0.28.5](https://github.com/vmware/govmomi/compare/v0.28.4...v0.28.5) + +> Release Date: 2022-09-30 + +### ⚠️ BREAKING + +### 📖 Commits + + + +## [Release v0.28.4](https://github.com/vmware/govmomi/compare/v0.28.3...v0.28.4) + +> Release Date: 2022-10-01 + +### ⚠️ BREAKING + +### 📖 Commits + + + +## [Release v0.28.3](https://github.com/vmware/govmomi/compare/v0.28.1...v0.28.3) + +> Release Date: 2022-09-30 + +### 🐞 Fix + +- [371a24a4] Interface conversion panic in pkg simulator +- [a982c033] use correct controlflag for vslm SetControlFlags API test +- [310516e2] govc: disambiguate vm/host search flags in vm.migrate +- [6af2cdc3] govc-tests in Go v1.18 +- [142cdca4] Security update golangci-lint +- [971079ba] use correct vcenter.DeploymentSpec.VmConfigSpec json tag + +### 💫 API Changes + +- [ca7ee510] add VmConfigSpec field to content library DeploymentSpec + +### 💫 `govc` (CLI) + +- [515ca29f] Use unique searchFlagKey when calling NewSearchFlag +- [9d4ca658] add library.deploy '-config' flag +- [fc17df08] add 'device.clock.add' command +- [11f2d453] Edit disk storage IO + +### 💫 `vcsim` (Simulator) + +- [578b95e5] Fix createVM to encode VM name +- [3325da0c] add content library VmConfigSpec support +- [8928a489] Update Dockerfile + +### 🧹 Chore + +- [e1f76e37] Add missing copyright header +- [6ed812fe] Add Go boilerplate check + +### ⚠️ BREAKING + +### 📖 Commits + +- [11e89157] new to go hence fixing coding errors +- [e5ffb4a6] fixed syntax errors +- [b62ddfaa] fixing header check failure +- [9e97647e] Fixing UT failures +- [2fd7d28f] adding support for LLDP and CDP details for GOVC and VCSIM +- [578b95e5] vcsim: Fix createVM to encode VM name +- [371a24a4] fix: Interface conversion panic in pkg simulator +- [a982c033] fix: use correct controlflag for vslm SetControlFlags API test +- [310516e2] fix: govc: disambiguate vm/host search flags in vm.migrate +- [5929abfb] correct SetControlFlags and ClearControlFlags APIs +- [6af2cdc3] fix: govc-tests in Go v1.18 +- [e1f76e37] chore: Add missing copyright header +- [6ed812fe] chore: Add Go boilerplate check +- [142cdca4] fix: Security update golangci-lint +- [3f4993d4] build(deps): bump chuhlomin/render-template from 1.4 to 1.5 +- [971079ba] fix: use correct vcenter.DeploymentSpec.VmConfigSpec json tag +- [892dcfcc] build(deps): bump nokogiri from 1.13.5 to 1.13.6 in /gen +- [303f0d95] build(deps): bump goreleaser/goreleaser-action from 2 to 3 +- [7eef76c3] build(deps): bump nokogiri from 1.13.4 to 1.13.5 in /gen +- [515ca29f] govc: Use unique searchFlagKey when calling NewSearchFlag +- [9d4ca658] govc: add library.deploy '-config' flag +- [c5ebd552] fix:fail to add ssd disk into allflash disk group Closes: [#2846](https://github.com/vmware/govmomi/issues/2846) +- [88f48e02] Updated USAGE.md +- [3325da0c] vcsim: add content library VmConfigSpec support +- [ca7ee510] api: add VmConfigSpec field to content library DeploymentSpec +- [8928a489] vcsim: Update Dockerfile +- [bf5d054d] Fixed docs for govc library.info w/-json +- [2f9fab55] emacs: fix json mode +- [fc17df08] govc: add 'device.clock.add' command +- [11f2d453] govc: Edit disk storage IO + + +## [Release v0.28.1](https://github.com/vmware/govmomi/compare/v0.28.0...v0.28.1) + +> Release Date: 2023-01-27 + +### 🐞 Fix + +- [c27ab6b9] use correct controlflag for vslm SetControlFlags API test + +### ⚠️ BREAKING + +### 📖 Commits + +- [205cbcdc] lookup.EndpointURL should only save thumbprints for endpoints outside of vCenter +- [c27ab6b9] fix: use correct controlflag for vslm SetControlFlags API test +- [8d43c82c] correct SetControlFlags and ClearControlFlags APIs + + +## [Release v0.28.0](https://github.com/vmware/govmomi/compare/v0.27.5...v0.28.0) + +> Release Date: 2022-04-27 + +### 🐞 Fix + +- [5ef4aaaf] DiskFileOperation must consider both capacity fields +- [3566a35d] govc guest validate username/password +- [bbbfd7bc] govc test workflow cp error +- [a587742b] avoid debug trace if http.Request.Body is nil +- [7e2ce135] Ignore concurrent deletes in GetCategories +- [a7c6f15b] Allow go 1.17 to go install +- [0f0201ad] vapi - special param encoding for edge cluster lookup +- [e5209e34] rest.Client.LoginByToken invalid signature +- [ad66761e] support govc import.spec for remote ova +- [ebeaa71b] Add IPv6 support for signing HTTP request +- [512c168e] govc vm.destroy only destroys the 1st argument +- [d25aba08] govc vcsa.net.proxy.info doesnt give output in json format +- [ac7c9bf9] avoid possible panic in HostSystem.ManagementIPs +- [10fec668] CHANGELOG sorting and generation + +### 💡 Examples + +- [c5826b8f] Add Alarm Manager Example +- [9617bded] add HostConfigManager_OptionManager +- [a1a9d848] add VirtualDeviceList_SelectByBackingInfo + +### 💫 API Changes + +- [61c40001] add GPU support to VirtualDeviceList.SelectByBackingInfo + +### 💫 `govc` (CLI) + +- [d8dd7f2b] Add CLI command cluster.module +- [49a83e71] Fix arguments validation in datastore.disk.inflate/shrink +- [01d31b53] Add Feature dvs.create '-num-uplinks' flag +- [40e6cbc8] Add Appliance access API +- [949ef572] Add Appliance shutdown API's +- [d5ed6855] Add support for VM hardware upgrade scheduling +- [742f2893] add support for supervisor services deploy +- [3ba25d70] Require full or absolute paths +- [a4ae62e7] Add library info command +- [8fde8bce] validate library.deploy arguments + +### 💫 `vcsim` (Simulator) + +- [3d8ddf16] Fix device connectivity when vm is powered off +- [111ad9fc] Use new action type in simulator PlaceVmsXCluster response +- [e92db045] Fix NFS datastore moid collision +- [16e6bace] set summary.guest.{hostName,ipAddress} in CustomizeVM +- [46a85642] add ssoadmin simulator +- [811b829c] Fix port filtering by criteria in FetchDVPorts +- [e8425be5] revert vapi.Status() method +- [451ec35a] Fix keys in DistributedVirtualPorts +- [6542ccb5] Fix CreateFolder to encode folder name +- [8629c499] Allow updating custom fields +- [93c2afd1] copy device list when cloning a VM +- [3214d97a] add support for cloning HostSystems +- [9b3d6353] Fix distribute VMs across resource pools +- [93d39917] Add TenantManager support in simulator +- [6de12ab7] allow VM PowerOff when Host is in maintenance mode +- [48f7a881] emit VmMigratedEvent in RelocateVM method + +### 📃 Documentation + +- [9ea287c2] Update documentation +- [b4a2d3b3] Add git blog post to CONTRIBUTING +- [c7e103e7] Clarify squash in CONTRIBUTING +- [9317bdaf] Update CONTIRBUTING.md file + +### 🧹 Chore + +- [d60b21d5] Optimize Go CI workflows +- [2d72f576] Add dependabot configuration +- [5c301091] Use powerclicore on ghcr.io +- [7d8af1e7] Update CI to Go 1.18 +- [205c0e0d] Add api: commit prefix +- [b6cd7c1b] Add link to Discussions in New Issue +- [15efe49f] Replace /rest with /api in vcsa.shutdown API's +- [db7edbf4] Update workflow Go versions +- [05c28f4a] upgrade go directive in go.mod to 1.17 +- [ebff29b7] Add notes to PR RELEASE workflow + +### ⚠️ BREAKING + +Fix distribute VMs across resource pools [9b3d6353]: +The name of virtual machines deployed in `vcsim` in a cluster (and +optionally child resource pools) has changed to include the +corresponding resource pool name. VM names deployed to standalone hosts +in `vcsim` are not changed. + +### 📖 Commits + +- [9ea287c2] docs: Update documentation +- [89ae0933] build(deps): bump actions/stale from 3 to 5 +- [d60b21d5] chore: Optimize Go CI workflows +- [0d1b4189] build(deps): bump peter-evans/create-or-update-comment from 1 to 2 +- [e85b164d] build(deps): bump github/codeql-action from 1 to 2 +- [5ef4aaaf] fix: DiskFileOperation must consider both capacity fields +- [3566a35d] fix: govc guest validate username/password +- [1f0f8cc8] build(deps): bump chuhlomin/render-template from 1.2 to 1.4 +- [7324f647] build(deps): bump actions/upload-artifact from 2 to 3 +- [808a439a] build(deps): bump peter-evans/create-pull-request from 3 to 4 +- [bdee9992] build(deps): bump github.com/google/uuid from 1.2.0 to 1.3.0 +- [2d72f576] chore: Add dependabot configuration +- [bbbfd7bc] fix: govc test workflow cp error +- [d8dd7f2b] govc: Add CLI command cluster.module +- [90c90a0a] build(deps): bump nokogiri from 1.13.2 to 1.13.4 in /gen +- [3cb3eff1] ConfigInfo2ConfigSpec +- [3d8ddf16] vcsim: Fix device connectivity when vm is powered off +- [b4a2d3b3] docs: Add git blog post to CONTRIBUTING +- [49a83e71] govc: Fix arguments validation in datastore.disk.inflate/shrink +- [5c301091] chore: Use powerclicore on ghcr.io +- [7d8af1e7] chore: Update CI to Go 1.18 +- [111ad9fc] vcsim: Use new action type in simulator PlaceVmsXCluster response +- [c5826b8f] examples: Add Alarm Manager Example +- [46583051] Move the ClusterClusterInitialPlacementAction to unreleased types + fix linter error +- [9b1de9c8] Fix a linter error +- [cb2b8f5c] Add a new type of cluster action used for placing a VM. This action inherits from InitialPlacement action because it conveys the resource pool and host for placing the VM. In addition, it also has the VM's ConfigSpecwhich is used for indicating the recommended datastore for each virtual disk in VM's ConfigSpec +- [9617bded] examples: add HostConfigManager_OptionManager +- [8e4054fa] adding a check that number of uplinks otherwise do default +- [aada9aa1] Reconfigure LACP API for DVS +- [a1a9d848] examples: add VirtualDeviceList_SelectByBackingInfo +- [61c40001] api: add GPU support to VirtualDeviceList.SelectByBackingInfo +- [e92db045] vcsim: Fix NFS datastore moid collision +- [01d31b53] govc: Add Feature dvs.create '-num-uplinks' flag +- [11e469a4] build(deps): bump nokogiri from 1.12.5 to 1.13.2 in /gen +- [547c63fd] Added Support for vrdma NIC Type Signed-off-by: C S P Nanda +- [205c0e0d] chore: Add api: commit prefix +- [b6cd7c1b] chore: Add link to Discussions in New Issue +- [15efe49f] chore: Replace /rest with /api in vcsa.shutdown API's +- [40e6cbc8] govc: Add Appliance access API +- [16e6bace] vcsim: set summary.guest.{hostName,ipAddress} in CustomizeVM +- [a587742b] fix: avoid debug trace if http.Request.Body is nil +- [7e2ce135] fix: Ignore concurrent deletes in GetCategories +- [1875bac1] Add PlaceVmsXCluster bindings and simulator +- [a7c6f15b] fix: Allow go 1.17 to go install +- [a5498b89] Add BackingDiskObjectId go bindings to CNS API +- [0f0201ad] fix: vapi - special param encoding for edge cluster lookup +- [46a85642] vcsim: add ssoadmin simulator +- [297a3cae] ssoadmin: add IdentitySources API bindings +- [811b829c] vcsim: Fix port filtering by criteria in FetchDVPorts +- [e5209e34] fix: rest.Client.LoginByToken invalid signature +- [c7e103e7] docs: Clarify squash in CONTRIBUTING +- [e8425be5] vcsim: revert vapi.Status() method +- [ad66761e] fix: support govc import.spec for remote ova +- [803b6362] sts: support issuing HoK token using HoK token +- [451ec35a] vcsim: Fix keys in DistributedVirtualPorts +- [949ef572] govc: Add Appliance shutdown API's +- [6542ccb5] vcsim: Fix CreateFolder to encode folder name +- [d5ed6855] govc: Add support for VM hardware upgrade scheduling +- [9317bdaf] docs: Update CONTIRBUTING.md file +- [8629c499] vcsim: Allow updating custom fields +- [93c2afd1] vcsim: copy device list when cloning a VM +- [ebeaa71b] fix: Add IPv6 support for signing HTTP request +- [b729a862] Fix typo in (simulator.Context).WithLock() comment +- [cd577f46] Fixed doc +- [ca1f45ae] Added command flag documentation +- [512240a0] Fixed goimports issues +- [ce88635f] Added vm::ExportSnapshot and snapshot flag to export.ovf +- [742f2893] govc: add support for supervisor services deploy +- [3214d97a] vcsim: add support for cloning HostSystems +- [3ba25d70] govc: Require full or absolute paths +- [db7edbf4] chore: Update workflow Go versions +- [512c168e] fix: govc vm.destroy only destroys the 1st argument +- [b51418e3] Add IsAlreadyExists error helper +- [05c28f4a] chore: upgrade go directive in go.mod to 1.17 +- [a4ae62e7] govc: Add library info command +- [d25aba08] fix: govc vcsa.net.proxy.info doesnt give output in json format +- [ac7c9bf9] fix: avoid possible panic in HostSystem.ManagementIPs +- [9b3d6353] vcsim: Fix distribute VMs across resource pools +- [1da8c5e8] Fix: Deep compare error types in simulator VM tests +- [d3eaa9b9] Support Creating/Reconfiguring a simulator VM with VApp properties +- [10fec668] fix: CHANGELOG sorting and generation +- [b05ed4e0] Independent simulator.Context per-subtask in PowerOnMultiVM. +- [a0224d91] Fix eam/simulator tests +- [e2498fb8] Change references from global Map to ctx.Map. +- [ab446838] Set the Context.Map's when global Map is set +- [3b86fd0c] Re-work TenantManager addition to ServiceContent for older clients +- [93d39917] vcsim: Add TenantManager support in simulator +- [9f737e00] fix updating stale url from Makefile +- [8fde8bce] govc: validate library.deploy arguments +- [6de12ab7] vcsim: allow VM PowerOff when Host is in maintenance mode +- [ebff29b7] chore: Add notes to PR RELEASE workflow +- [48f7a881] vcsim: emit VmMigratedEvent in RelocateVM method +- [bb4f739b] Support finding Portgroups by ID in Finder.Network + + +## [Release v0.27.5](https://github.com/vmware/govmomi/compare/v0.27.4...v0.27.5) + +> Release Date: 2022-06-02 + +### 🐞 Fix + +- [e97c9708] use correct controlflag for vslm SetControlFlags API test + +### ⚠️ BREAKING + +### 📖 Commits + +- [e97c9708] fix: use correct controlflag for vslm SetControlFlags API test +- [f8cf9ef7] correct SetControlFlags and ClearControlFlags APIs + + +## [Release v0.27.4](https://github.com/vmware/govmomi/compare/v0.27.3...v0.27.4) + +> Release Date: 2022-02-10 + +### 🐞 Fix + +- [285e80cd] avoid debug trace if http.Request.Body is nil +- [dde50904] Ignore concurrent deletes in GetCategories +- [cbc68fc0] rest.Client.LoginByToken invalid signature + +### 💫 `vcsim` (Simulator) + +- [df595d82] add ssoadmin simulator + +### ⚠️ BREAKING + +### 📖 Commits + +- [285e80cd] fix: avoid debug trace if http.Request.Body is nil +- [dde50904] fix: Ignore concurrent deletes in GetCategories +- [fc1fce62] Add PlaceVmsXCluster bindings and simulator +- [df595d82] vcsim: add ssoadmin simulator +- [9ca477aa] ssoadmin: add IdentitySources API bindings +- [24fe60f1] Add BackingDiskObjectId go bindings to CNS API +- [cbc68fc0] fix: rest.Client.LoginByToken invalid signature + + +## [Release v0.27.3](https://github.com/vmware/govmomi/compare/v0.27.2...v0.27.3) + +> Release Date: 2022-02-01 + +### 🐞 Fix + +- [2d7cd133] Add IPv6 support for signing HTTP request + +### ⚠️ BREAKING + +### 📖 Commits + +- [6b4e2391] sts: support issuing HoK token using HoK token +- [2d7cd133] fix: Add IPv6 support for signing HTTP request + + +## [Release v0.27.2](https://github.com/vmware/govmomi/compare/v0.27.1...v0.27.2) + +> Release Date: 2021-11-23 + +### 🐞 Fix + +- [f04d77d6] avoid possible panic in HostSystem.ManagementIPs + +### ⚠️ BREAKING + +### 📖 Commits + +- [f04d77d6] fix: avoid possible panic in HostSystem.ManagementIPs + + +## [Release v0.27.1](https://github.com/vmware/govmomi/compare/v0.27.0...v0.27.1) + +> Release Date: 2021-10-20 + +### ⚠️ BREAKING + +### 📖 Commits + +- [6209be5b] Support finding Portgroups by ID in Finder.Network + + +## [Release v0.27.0](https://github.com/vmware/govmomi/compare/v0.26.2...v0.27.0) + +> Release Date: 2021-10-14 + +### 🐞 Fix + +- [57c4be58] multi-value query params for vAPI methods +- [815e2d8f] avoid vNIC mapping in guest.TransferURL if URL.Host is an IP +- [81a7dbe9] avoid use of vNIC IP in guest.TransferURL if there are multiple +- [61afce31] Update CnsQueryAsync API request parameters to handle nil for QuerySelection +- [a601a8a8] generate negative device key + +### 💫 `govc` (CLI) + +- [b5426eba] Add feature to read file contents for ExtraConfig +- [85956c77] fix tasks to activate option dump/json/xml +- [f4ef4d93] Fix incorrect MoRef parsing +- [d695f4cf] Handle powered on VMs in vm.destroy +- [94f63681] add library.clone '-e' and '-m' options +- [2fcae372] add vsan info and change commands + +### 💫 `vcsim` (Simulator) + +- [fa457940] Fix PowerOnMultiVMTask() to return per-VM tasks +- [e67b1b11] check if VM host InMaintenanceMode + +### 📃 Documentation + +- [82e447d9] Update govc USAGE + +### 🧹 Chore + +- [05adcc97] Remove -i parameter in go install +- [18ea9cc5] Update PR and release docs + +### ⚠️ BREAKING + +Add task manager and collector [397c8aad]: +`event.Manager` does not embed `object.Common` anymore. Only the methods +`Client()` and `Reference()` are implemented. +`event.NewHistoryCollector()` is now unexported (to +`newHistoryCollector()`) as it was merely a helper and to comply with +the task manager implementation. + +### 📖 Commits + +- [78f30265] update contributors +- [68b54585] Refactor EAM code to use BaseAgencyConfigInfo interface instead of impl +- [d5ded1f0] Implement mo.Reference interface in task+event managers +- [038bc3d8] Update vslm types to vCenter 7.0U3 (build 18700403) +- [ae8161df] Update pbm types to vCenter 7.0U3 (build 18700403) +- [f2d167de] Update eam types to vCenter 7.0U3 (build 18700403) +- [f1c7b54d] Update vim25 types to vCenter 7.0U3 (build 18700403) +- [445fd552] Update gen.sh to vCenter 7.0U3 (build 18700403) +- [961f0ae6] example: find VirtualMachine's Cluster +- [57c4be58] fix: multi-value query params for vAPI methods +- [f7e8ed73] Set custom HTTP headers for VAPI calls +- [05adcc97] chore: Remove -i parameter in go install +- [82e447d9] docs: Update govc USAGE +- [b5426eba] govc: Add feature to read file contents for ExtraConfig +- [815e2d8f] fix: avoid vNIC mapping in guest.TransferURL if URL.Host is an IP +- [81a7dbe9] fix: avoid use of vNIC IP in guest.TransferURL if there are multiple +- [18ea9cc5] chore: Update PR and release docs +- [a66d23ed] build(deps): bump nokogiri from 1.11.4 to 1.12.5 in /gen +- [a853b300] Fix: Nil-Pointer Exception in ResourceAllocation +- [fa457940] vcsim: Fix PowerOnMultiVMTask() to return per-VM tasks +- [85956c77] govc: fix tasks to activate option dump/json/xml +- [61afce31] fix: Update CnsQueryAsync API request parameters to handle nil for QuerySelection +- [397c8aad] feat: Add task manager and collector +- [a601a8a8] fix: generate negative device key +- [f4ef4d93] govc: Fix incorrect MoRef parsing +- [e67b1b11] vcsim: check if VM host InMaintenanceMode +- [d695f4cf] govc: Handle powered on VMs in vm.destroy +- [a55fa7dc] feat: Add optional WaitOptions to WaitForUpdates +- [94f63681] govc: add library.clone '-e' and '-m' options +- [2fcae372] govc: add vsan info and change commands + + +## [Release v0.26.2](https://github.com/vmware/govmomi/compare/v0.26.1...v0.26.2) + +> Release Date: 2022-03-21 + +### 🐞 Fix + +- [76a22af3] avoid possible panic in HostSystem.ManagementIPs +- [566d2ac1] avoid use of vNIC IP in guest.TransferURL if there are multiple + +### ⚠️ BREAKING + +### 📖 Commits + +- [76a22af3] fix: avoid possible panic in HostSystem.ManagementIPs +- [566d2ac1] fix: avoid use of vNIC IP in guest.TransferURL if there are multiple + + +## [Release v0.26.1](https://github.com/vmware/govmomi/compare/v0.26.0...v0.26.1) + +> Release Date: 2021-08-16 + +### 🐞 Fix + +- [a366e352] Regenerated interface and type to include BaseAgencyConfigInfo. Closes: [#2545](https://github.com/vmware/govmomi/issues/2545). +- [d66ef551] explicitly import eam/simulator in test + +### 💡 Examples + +- [0c045a63] Add Property Wait example + +### 💫 `govc` (CLI) + +- [012f5348] support updating items in library.update command +- [5743d5b6] Allow cluster.change to set ClusterDrsConfigInfo.vmotionRate +- [03210c91] Add object.collect type flag alias help + +### 💫 `vcsim` (Simulator) + +- [ce6ed634] avoid race when fetching object Locker +- [31821de3] use 'domain-c' prefix for cluster moids +- [3625e6dd] propagate CustomizeVM MacAddress to Virtual NIC +- [389c0382] Take the host parameter into account while cloning a VM on a cluster +- [6fba1da7] Implement VSLM ExtendDisk_Task + +### 🧹 Chore + +- [ddc2b47a] Include commit details in BREAKING section + +### ⚠️ BREAKING + +### 📖 Commits + +- [a366e352] fix: Regenerated interface and type to include BaseAgencyConfigInfo. Closes: [#2545](https://github.com/vmware/govmomi/issues/2545). +- [655f8e5c] testing for lab +- [ce6ed634] vcsim: avoid race when fetching object Locker +- [31821de3] vcsim: use 'domain-c' prefix for cluster moids +- [0aa1de31] make processing of mac addresses case insensitive ([#2510](https://github.com/vmware/govmomi/issues/2510)) +- [012f5348] govc: support updating items in library.update command +- [0c045a63] examples: Add Property Wait example +- [f30cefc3] Add Reauth flag to skip loading cached sessions +- [3625e6dd] vcsim: propagate CustomizeVM MacAddress to Virtual NIC +- [5743d5b6] govc: Allow cluster.change to set ClusterDrsConfigInfo.vmotionRate +- [389c0382] vcsim: Take the host parameter into account while cloning a VM on a cluster +- [7bf48333] Added CNS querySnapshots binding, simulator testcases and client testcases +- [017ab414] Added CreateSnapshots and DeleteSnapshots methods in cns simulator as well as their test cases +- [03210c91] govc: Add object.collect type flag alias help +- [d66ef551] fix: explicitly import eam/simulator in test +- [ddc2b47a] chore: Include commit details in BREAKING section +- [6fba1da7] vcsim: Implement VSLM ExtendDisk_Task + + +## [Release v0.26.0](https://github.com/vmware/govmomi/compare/v0.25.0...v0.26.0) + +> Release Date: 2021-06-03 + +### 🐞 Fix + +- [70b92d6d] Isolate SSO govc tests + +### 💡 Examples + +- [81b1de17] add toolbox Client.Run + +### 💫 `govc` (CLI) + +- [e37e515b] fix default guest.run path for unsupported Windows guests +- [0e7012d0] Add support for getting the VC proxy and no-proxy configuration ([#2435](https://github.com/vmware/govmomi/issues/2435)) +- [6afb8ff9] Change 'Maintenance Mode' printing in host.info + +### 💫 `vcsim` (Simulator) + +- [dff7f6bb] fix panic in QueryPerfCounter method +- [df9dfde1] set VirtualMachine ChangeTrackingSupported property ([#2468](https://github.com/vmware/govmomi/issues/2468)) +- [0c0ed98a] fix race in CloneVM_Task +- [d01d0fa7] add simulator.RunContainer method +- [8ab0c99a] untie datastore capacity from local fs +- [d31941c8] Modify Usage of README. (based on v0.25.0) +- [4fea687c] include all namespaces in /about info +- [bd3467d4] avoid edit device panic when DeviceInfo is nil +- [35a42af5] add guest operations process support + +### 📃 Documentation + +- [75eee8e4] update govc/USAGE and CONTRIBUTORS +- [1f795d21] Add blog to vcsim README +- [2719c229] Document linker and GOFLAGS for build vars + +### 🧹 Chore + +- [b4e1f965] Fix CONTRIB link in greeting +- [6f2597be] Update CHANGELOG implementation +- [d3944e17] Add and reorder commits in CHANGELOG +- [a796d3fc] Add make help target +- [8bc8fd28] Add issue and PR templates +- [60e33916] Document commit prefixes +- [cac1d8d7] Add issue greeting +- [0f1c3f89] Add WIP Action +- [921ad37a] Remove dep files +- [1d4ce94a] Clean up documentation +- [991278b9] Remove unused release script +- [16d8add5] Automate CHANGELOG + +### ⚠️ BREAKING + +### 📖 Commits + +- [75eee8e4] docs: update govc/USAGE and CONTRIBUTORS +- [dff7f6bb] vcsim: fix panic in QueryPerfCounter method +- [b4e1f965] chore: Fix CONTRIB link in greeting +- [df9dfde1] vcsim: set VirtualMachine ChangeTrackingSupported property ([#2468](https://github.com/vmware/govmomi/issues/2468)) +- [8cbe64c5] Fix: Protect FileProvider.files to avoid concurrent modification +- [6f2597be] chore: Update CHANGELOG implementation +- [0c0ed98a] vcsim: fix race in CloneVM_Task +- [81b1de17] examples: add toolbox Client.Run +- [d01d0fa7] vcsim: add simulator.RunContainer method +- [9223b5ae] Add toolbox.NewClient method +- [8ab0c99a] vcsim: untie datastore capacity from local fs +- [e37e515b] govc: fix default guest.run path for unsupported Windows guests +- [d3944e17] chore: Add and reorder commits in CHANGELOG +- [83e29c69] Update GitHub Test Action to use Makefile +- [a7f2c47e] Update vslm types vC build 17986435 (7.0U2HP4) +- [067374fd] Update sms types vC build 17986435 (7.0U2HP4) +- [d9f507f0] Update pbm types vC build 17986435 (7.0U2HP4) +- [c89f8dd5] Update eam types vC build 17986435 (7.0U2HP4) +- [b72432ef] Update vim25 types vC build 17986435 (7.0U2HP4) +- [e53716dd] Update gen.sh to vC build 17986435 (7.0U2HP4) +- [1f795d21] docs: Add blog to vcsim README +- [338f5529] Ran "make fix" to correct lint issues +- [23d77ba4] Add support for golangci-lint +- [d31941c8] vcsim: Modify Usage of README. (based on v0.25.0) +- [7046a0d3] Support pre-auth handlers in vC Sim +- [2e8860d1] Add CNS Snapshot APIs in govmomi +- [13d4d376] Remove vendor +- [a796d3fc] chore: Add make help target +- [ef824a20] Fix QueryAsyncVolume API test to be invoked only for vSphere 7.0.3 +- [c1900234] Fix data race in simulator.container.id +- [3212351e] install bin doc: permalink to latest version +- [7d779833] Setup CodeQL Analysis +- [566250ff] build(deps): bump nokogiri from 1.11.1 to 1.11.4 in /gen +- [f814a9ca] ESX Agent Manager (EAM) Client and Simulator +- [0e7012d0] govc: Add support for getting the VC proxy and no-proxy configuration ([#2435](https://github.com/vmware/govmomi/issues/2435)) +- [8bc8fd28] chore: Add issue and PR templates +- [4fea687c] vcsim: include all namespaces in /about info +- [bd3467d4] vcsim: avoid edit device panic when DeviceInfo is nil +- [70b92d6d] fix: Isolate SSO govc tests +- [80c9053e] Correcting broken Kubernetes vSphere Cloud Provider links +- [60e33916] chore: Document commit prefixes +- [57a141f3] Update govc test docs with act +- [ff578914] Use "vcsim uuidgen" for bats tests +- [61e12ddb] Only greet unassociated users +- [e39dfdc8] Add chore section to CHANGELOG +- [6afb8ff9] govc: Change 'Maintenance Mode' printing in host.info +- [cac1d8d7] chore: Add issue greeting +- [0f1c3f89] chore: Add WIP Action +- [921ad37a] chore: Remove dep files +- [2719c229] docs: Document linker and GOFLAGS for build vars +- [f3645a96] Clarify SetRootCAs behavior +- [c368e57f] toolbox: add hgfs freebsd stub +- [35a42af5] vcsim: add guest operations process support +- [64e55d81] Set RoundTripper in ssoadmin.NewClient +- [1d4ce94a] chore: Clean up documentation +- [991278b9] chore: Remove unused release script +- [16d8add5] chore: Automate CHANGELOG +- [e8805c92] Add NotFoundFault in cns types +- [8576fe27] Add queryAsyncVolume in simulator +- [4b9e0813] Simplify binary download instructions +- [3062dda9] Remove Travis CI +- [0be5632f] adding rancher to projects and reorganizing in alpha order +- [4a63a28c] Add bindings for CnsQueryAsyncVolume API +- [a8c80b93] Update READMEs with artifacts and Docker images +- [26c9690c] Fix VM Guest test and vet warnings +- [a32cd0b3] Add RELEASE documentation +- [cc660b0e] Increase govc tests timeout +- [d7bfaf4f] toolbox: move process management to its own package +- [e86da96e] Exclude go files in release tarball + + +## [Release v0.25.0](https://github.com/vmware/govmomi/compare/v0.24.2...v0.25.0) + +> Release Date: 2021-04-16 + +### 💡 Examples + +- [38da87ff] add NetworkReference.EthernetCardBackingInfo + +### 💫 `govc` (CLI) + +- [1ac314c3] add vm.customize -dns-suffix flag +- [60e0e895] update test images URL +- [cdf3ace6] log invalid NetworkMapping.Name with import.ova command +- [f8b3d8a8] revert pretty print pruning optimization +- [35481467] add library.update command +- [749c2239] add session.ls -S flag +- [93245c1e] add tree command +- [790f9ce6] include sub task fault messages on failure +- [d2a353ba] remove device.boot -firmware default +- [de6032e0] add '-trace' and '-verbose' flags +- [63bb5c1e] metric command enhancements and fixes +- [7844a8c2] fix vm.migrate search index flags +- [5dacf627] fix cluster.usage Free field +- [f71bcf25] fix session curl when given a URL query +- [c954c2a5] validate license.remove +- [3b25c3f1] validate required library.clone NAME arg +- [344b7a30] note 'disk.ls -R' in volume.rm help +- [8942055a] add device.info examples to get disk UUID and vmdk +- [1b0af949] fix vm.markasvm examples +- [add8be5a] fix incorrect DeviceID value in device.pci.add +- [1f4f5640] add IPv6 support to vm.customize + +### 💫 `vcsim` (Simulator) + +- [27d8d2e4] put verbose logging behind '-trace' flag +- [0ef4ae22] add moid value mapping mappings +- [082f9927] add vsan simulator +- [25970530] fix Task.Info.Entity in RevertToSnapshot_Task +- [f0a045ac] set VirtualMachine.Config.CreateDate property +- [e51eb2b9] support EventFilterSpec.Time +- [8e45fa4a] emit CustomizationSucceeded event from CustomizeVM +- [c000bd6e] add DistributedVirtualSwitchManager +- [bcd5fa87] set VirtualDisk backing UUID +- [ccdcbe89] move product suffix in ServiceContent.About +- [393e7330] use linked list for EventHistoryCollector +- [9c4dc1a1] escape datastore name +- [9c2fe70f] record/replay EnvironmentBrowser.QueryConfigOption +- [5fd7e264] fix EventHistoryCollector fixes +- [0b755a59] switch bats tests from esx to vcsim env +- [3f1caf82] fixes for PowerCLI Get-VirtualNetwork + +### 📃 Documentation + +- [e18b601f] update for 0.25 release + +### ⚠️ BREAKING + +### 📖 Commits + +- [6fe8d60a] Fix folder write for govc container +- [e18b601f] docs: update for 0.25 release +- [1ac314c3] govc: add vm.customize -dns-suffix flag +- [22d911f6] Add Cron Docker Login Action +- [60e0e895] govc: update test images URL +- [3385b3e0] Add action to automate release +- [cdf3ace6] govc: log invalid NetworkMapping.Name with import.ova command +- [27d8d2e4] vcsim: put verbose logging behind '-trace' flag +- [f8b3d8a8] govc: revert pretty print pruning optimization +- [0ef4ae22] vcsim: add moid value mapping mappings +- [df08d4b2] First step towards release automation +- [f9b79a4f] export simulator.task.Wait() +- [917c4ec8] Ensure lock hand-off to simulator.Task goroutine +- [b45b228f] Simulator Task Delay +- [4b59b652] Make Simulator Tasks Async +- [bc52c793] Associate every registry lock with a Context. +- [054971ee] Wait until VM creation completes before adding to folder +- [35481467] govc: add library.update command +- [7403b470] Fix race in simulator's PropertyCollector +- [aadb2082] Add action to block WIP PRs +- [749c2239] govc: add session.ls -S flag +- [bc297330] [3ad0f415] Update Dockerfiles and .goreleaser.yml +- [082f9927] vcsim: add vsan simulator +- [8c38d56d] Add a stretched cluster conversion command. +- [408c531a] gofmt +- [e8a6b126] Update govc/flags/output.go +- [bf54a7c4] Add more badges +- [93245c1e] govc: add tree command +- [790f9ce6] govc: include sub task fault messages on failure +- [07e6e923] Use Github Actions Status Badges +- [d2a353ba] govc: remove device.boot -firmware default +- [4ed615f6] Add chainable RoundTripper support to endpoint clients +- [bab95d26] Add the vSAN stretched cluster reference. +- [6ff33db7] Fix events example +- [de6032e0] govc: add '-trace' and '-verbose' flags +- [7aae8dfb] Add support for calling vCenter for VLSM ExtendDisk and InflateDisk +- [7a276bf6] Add client test file for vslm package to validate register disk and cns create volume +- [dc29aa29] Fix performance.Manager.SampleByName truncation +- [18b53fd2] Added UpdateServiceMessage to Session Manager +- [63bb5c1e] govc: metric command enhancements and fixes +- [7844a8c2] govc: fix vm.migrate search index flags +- [7ab111bd] Drop clusterDistribution from vSAN 7.0 update and create spec elements +- [2c57a8a3] Use Github Actions +- [52631496] Marshal soapFaultError as JSON +- [f9e323a6] fix tab indentation +- [ae129ba0] add tests and implement HA Ready Condition +- [f34b3fa2] implement vSphere HA additional delay to VM HA overrides in govc +- [25970530] vcsim: fix Task.Info.Entity in RevertToSnapshot_Task +- [5dacf627] govc: fix cluster.usage Free field +- [0d155a61] Handling invalid reader size +- [b70542a5] Using progress reader in WriteFile +- [b7f9e034] use correct enum for vm restart priority +- [d3d49a36] Add support for snapshot size calculations +- [61bfa072] Use a dash to indicate empty address +- [f0a045ac] vcsim: set VirtualMachine.Config.CreateDate property +- [4d9a9000] vim25: fix race in TemporaryNetworkError retry func +- [2f14e4b2] ovf: add Config and ExtraConfig to VirtualHardwareSection +- [50328780] Add vSAN 7.0U1 release constant +- [886573de] Update .goreleaser.yml +- [1cdb3164] Change the address type to automatic +- [667a3791] Remove duplicate cns bindings from vsan directory +- [f71bcf25] govc: fix session curl when given a URL query +- [d92f41de] Update volume ACL spec to add delete field +- [c954c2a5] govc: validate license.remove +- [2a4f8c8a] Update ConfigureVolumeACLs bindings in cns types +- [3b25c3f1] govc: validate required library.clone NAME arg +- [344b7a30] govc: note 'disk.ls -R' in volume.rm help +- [8942055a] govc: add device.info examples to get disk UUID and vmdk +- [1b0af949] govc: fix vm.markasvm examples +- [543e52ea] govc-env --save default +- [0a5f2a99] Little fix for "govc-env --save without config name" +- [4a7a0b45] gen: require nokogiri 1.11.0 or higher +- [add8be5a] govc: fix incorrect DeviceID value in device.pci.add +- [e51eb2b9] vcsim: support EventFilterSpec.Time +- [1f4f5640] govc: add IPv6 support to vm.customize +- [8e45fa4a] vcsim: emit CustomizationSucceeded event from CustomizeVM +- [c000bd6e] vcsim: add DistributedVirtualSwitchManager +- [bcd5fa87] vcsim: set VirtualDisk backing UUID +- [ccdcbe89] vcsim: move product suffix in ServiceContent.About +- [393e7330] vcsim: use linked list for EventHistoryCollector +- [9c4dc1a1] vcsim: escape datastore name +- [9c2fe70f] vcsim: record/replay EnvironmentBrowser.QueryConfigOption +- [5fd7e264] vcsim: fix EventHistoryCollector fixes +- [40a2cf0b] Skip tests that require docker on TravisCI +- [00ee2911] toolbox: skip tests that require Linux +- [0b755a59] vcsim: switch bats tests from esx to vcsim env +- [c6d5264a] Updated projects to include VMware Event Broker Appliance +- [ae44a547] ExampleCollector_Retrieve: Add missing err return +- [38da87ff] examples: add NetworkReference.EthernetCardBackingInfo +- [3f1caf82] vcsim: fixes for PowerCLI Get-VirtualNetwork +- [041a98b8] Fix DvsNetworkRuleQualifier interface +- [44e05fe4] SHA-1 deprecated in 2011, sha256sum for releases + + +## [Release v0.24.2](https://github.com/vmware/govmomi/compare/v0.24.1...v0.24.2) + +> Release Date: 2021-10-14 + +### 🐞 Fix + +- [b18f06b5] avoid vNIC mapping in guest.TransferURL if URL.Host is an IP +- [5a2a8aba] avoid use of vNIC IP in guest.TransferURL if there are multiple + +### ⚠️ BREAKING + +### 📖 Commits + +- [b18f06b5] fix: avoid vNIC mapping in guest.TransferURL if URL.Host is an IP +- [5a2a8aba] fix: avoid use of vNIC IP in guest.TransferURL if there are multiple + + +## [Release v0.24.1](https://github.com/vmware/govmomi/compare/v0.24.0...v0.24.1) + +> Release Date: 2021-03-17 + +### 💡 Examples + +- [38da87ff] add NetworkReference.EthernetCardBackingInfo + +### 💫 `govc` (CLI) + +- [63bb5c1e] metric command enhancements and fixes +- [7844a8c2] fix vm.migrate search index flags +- [5dacf627] fix cluster.usage Free field +- [f71bcf25] fix session curl when given a URL query +- [c954c2a5] validate license.remove +- [3b25c3f1] validate required library.clone NAME arg +- [344b7a30] note 'disk.ls -R' in volume.rm help +- [8942055a] add device.info examples to get disk UUID and vmdk +- [1b0af949] fix vm.markasvm examples +- [add8be5a] fix incorrect DeviceID value in device.pci.add +- [1f4f5640] add IPv6 support to vm.customize + +### 💫 `vcsim` (Simulator) + +- [25970530] fix Task.Info.Entity in RevertToSnapshot_Task +- [f0a045ac] set VirtualMachine.Config.CreateDate property +- [e51eb2b9] support EventFilterSpec.Time +- [8e45fa4a] emit CustomizationSucceeded event from CustomizeVM +- [c000bd6e] add DistributedVirtualSwitchManager +- [bcd5fa87] set VirtualDisk backing UUID +- [ccdcbe89] move product suffix in ServiceContent.About +- [393e7330] use linked list for EventHistoryCollector +- [9c4dc1a1] escape datastore name +- [9c2fe70f] record/replay EnvironmentBrowser.QueryConfigOption +- [5fd7e264] fix EventHistoryCollector fixes +- [0b755a59] switch bats tests from esx to vcsim env +- [3f1caf82] fixes for PowerCLI Get-VirtualNetwork + +### ⚠️ BREAKING + +### 📖 Commits + +- [7a276bf6] Add client test file for vslm package to validate register disk and cns create volume +- [dc29aa29] Fix performance.Manager.SampleByName truncation +- [18b53fd2] Added UpdateServiceMessage to Session Manager +- [63bb5c1e] govc: metric command enhancements and fixes +- [7844a8c2] govc: fix vm.migrate search index flags +- [7ab111bd] Drop clusterDistribution from vSAN 7.0 update and create spec elements +- [52631496] Marshal soapFaultError as JSON +- [f9e323a6] fix tab indentation +- [ae129ba0] add tests and implement HA Ready Condition +- [f34b3fa2] implement vSphere HA additional delay to VM HA overrides in govc +- [25970530] vcsim: fix Task.Info.Entity in RevertToSnapshot_Task +- [5dacf627] govc: fix cluster.usage Free field +- [b7f9e034] use correct enum for vm restart priority +- [d3d49a36] Add support for snapshot size calculations +- [61bfa072] Use a dash to indicate empty address +- [f0a045ac] vcsim: set VirtualMachine.Config.CreateDate property +- [4d9a9000] vim25: fix race in TemporaryNetworkError retry func +- [2f14e4b2] ovf: add Config and ExtraConfig to VirtualHardwareSection +- [50328780] Add vSAN 7.0U1 release constant +- [886573de] Update .goreleaser.yml +- [1cdb3164] Change the address type to automatic +- [667a3791] Remove duplicate cns bindings from vsan directory +- [f71bcf25] govc: fix session curl when given a URL query +- [d92f41de] Update volume ACL spec to add delete field +- [c954c2a5] govc: validate license.remove +- [2a4f8c8a] Update ConfigureVolumeACLs bindings in cns types +- [3b25c3f1] govc: validate required library.clone NAME arg +- [344b7a30] govc: note 'disk.ls -R' in volume.rm help +- [8942055a] govc: add device.info examples to get disk UUID and vmdk +- [1b0af949] govc: fix vm.markasvm examples +- [543e52ea] govc-env --save default +- [0a5f2a99] Little fix for "govc-env --save without config name" +- [4a7a0b45] gen: require nokogiri 1.11.0 or higher +- [add8be5a] govc: fix incorrect DeviceID value in device.pci.add +- [e51eb2b9] vcsim: support EventFilterSpec.Time +- [1f4f5640] govc: add IPv6 support to vm.customize +- [8e45fa4a] vcsim: emit CustomizationSucceeded event from CustomizeVM +- [c000bd6e] vcsim: add DistributedVirtualSwitchManager +- [bcd5fa87] vcsim: set VirtualDisk backing UUID +- [ccdcbe89] vcsim: move product suffix in ServiceContent.About +- [393e7330] vcsim: use linked list for EventHistoryCollector +- [9c4dc1a1] vcsim: escape datastore name +- [9c2fe70f] vcsim: record/replay EnvironmentBrowser.QueryConfigOption +- [5fd7e264] vcsim: fix EventHistoryCollector fixes +- [40a2cf0b] Skip tests that require docker on TravisCI +- [00ee2911] toolbox: skip tests that require Linux +- [0b755a59] vcsim: switch bats tests from esx to vcsim env +- [c6d5264a] Updated projects to include VMware Event Broker Appliance +- [ae44a547] ExampleCollector_Retrieve: Add missing err return +- [38da87ff] examples: add NetworkReference.EthernetCardBackingInfo +- [3f1caf82] vcsim: fixes for PowerCLI Get-VirtualNetwork +- [041a98b8] Fix DvsNetworkRuleQualifier interface +- [44e05fe4] SHA-1 deprecated in 2011, sha256sum for releases + + +## [Release v0.24.0](https://github.com/vmware/govmomi/compare/v0.23.1...v0.24.0) + +> Release Date: 2020-12-21 + +### 💡 Examples + +- [7178588c] add Folder.CreateVM +- [b4f7243b] add ContainerView retrieve clusters +- [1d21fff9] use session.Cache +- [8af8cef6] add events +- [e153061f] fix simulator.RunContainer on MacOSX + +### 💫 `govc` (CLI) + +- [1ec59a7c] fix build.sh git tag injection +- [31c0836e] add cluster.usage command +- [79514c81] add volume.ls -ds option +- [5e57b3f6] add device.boot -firmware option +- [4d82f0ff] add dvs.portgroup.{add,change} '-auto-expand' flag +- [4a1d05ac] fix object.collect ContainerView updates +- [e84d0d18] document vm.disk.attach -link behavior +- [70a9ced4] fix vm.clone panic when target VM already exists +- [a97e6168] support sparse backing in vm.disk.change +- [3380cd30] add CNS volume ls and rm commands +- [f7170fd2] add find -p flag +- [b40cdd8a] add storage.policy commands +- [d0111d28] add vm.console -wss flag +- [86374ea2] support multi value flags in host.esxcli command +- [ebcfa3d4] add namespace.cluster.ls command + +### 💫 `vcsim` (Simulator) + +- [bf80efab] include stderr in log message when volume import fails +- [1f3fb17c] include stderr in log message when container fails to start +- [e1c4b06e] rewrite vmfs path from saved model +- [bcdfb298] QueryConfigOptionEx Spec is optional +- [73e1af55] support inventory updates in ContainerView +- [a76123b2] set VirtualDevice.Connectable default for removable devices +- [b195dd57] add AuthorizationManager methods +- [a71f6c77] set VirtualDisk backing option defaults +- [fbde3866] add CloneVApp_Task support +- [aae78223] fix ListView.Modify +- [9cca13ab] avoid ViewManager.ModifyListView race +- [156b1cb0] add ListView to race test +- [55f6f952] add mechanism for modeling methods +- [69942fe2] fix save/load property collection for VmwareDistributedVirtualSwitch +- [33121b87] Honoring the instance uuid provided in spec by caller ([#2052](https://github.com/vmware/govmomi/issues/2052)) + +### ⚠️ BREAKING + +### 📖 Commits + +- [1ec59a7c] govc: fix build.sh git tag injection +- [164b9217] Update docs for 0.24 release +- [bf80efab] vcsim: include stderr in log message when volume import fails +- [4080e177] Add batch APIs for multiple tags to object +- [31c0836e] govc: add cluster.usage command +- [7178588c] examples: add Folder.CreateVM +- [2b962f3f] Add test for vsan host config +- [165d7cb4] Add function to get vsan host config +- [79514c81] govc: add volume.ls -ds option +- [f7ff79df] Add Configure ACL go bindings +- [1f3fb17c] vcsim: include stderr in log message when container fails to start +- [3b83040a] Add wrappers for retrieving vsan properties +- [12e8969c] Use gofmt +- [6454dbd4] Add vSAN 7.0 API bindings +- [6a216a52] Add vSAN 7.0 API bindings +- [be15ad6c] Regenerate against vSphere 7.0U1 release +- [5e57b3f6] govc: add device.boot -firmware option +- [e1c4b06e] vcsim: rewrite vmfs path from saved model +- [26635452] Change CnsCreateVolume to return PlacementResult for static volume provisioning. Also add unit test for this case. +- [4d82f0ff] govc: add dvs.portgroup.{add,change} '-auto-expand' flag +- [bcdfb298] vcsim: QueryConfigOptionEx Spec is optional +- [8b194c23] Add Placement object in CNS CreateVolume response. Add corresponding test. +- [b085fc33] Use available ctx in enable cluster network lookup +- [f6f336ab] Cleanup some redundant code for cluster namespace enabling +- [d04f2b49] change negative one to rand neg int32 +- [f819befd] go binding for CNS RelocateVolume API +- [ed93ea7d] fix the goimports validation error +- [f402c0e1] support trunk mode port group +- [ff575977] change key default from -1 to rand neg int32 vsphere 7 introduced a key collision detection error when adding devices com.vmware.vim.vpxd.vmprov.duplicateDeviceKey which causes -1 keys to return an error of duplicate if you try and add two devices in the same AddDevice call +- [39acef43] Add option to disable secure cookies with non-TLS endpoints +- [ae19e30f] simulator: fix container vm example +- [73e1af55] vcsim: support inventory updates in ContainerView +- [593cd20d] Add namespace.cluster.disable cmd + formatting fixes +- [782ed95c] Add namespace.cluster.enable cmd to govc +- [e7403032] Make ListStorageProfiles public -> for enabling clusters in govc +- [53965796] Adds support for enabling cluster namespaces via API +- [4a1d05ac] govc: fix object.collect ContainerView updates +- [e84d0d18] govc: document vm.disk.attach -link behavior +- [a76123b2] vcsim: set VirtualDevice.Connectable default for removable devices +- [b4f7243b] examples: add ContainerView retrieve clusters +- [b195dd57] vcsim: add AuthorizationManager methods +- [a71f6c77] vcsim: set VirtualDisk backing option defaults +- [1d21fff9] examples: use session.Cache +- [8af8cef6] examples: add events +- [3e2a8071] Add ClusterDistribution field for CNS telemetry and Drop optional fields not known to the prior releases +- [4acfb726] Fix for fatal error: concurrent map iteration and map write +- [01610887] Adding VsanQueryObjectIdentities and QueryVsanObjects +- [fbde3866] vcsim: add CloneVApp_Task support +- [70a9ced4] govc: fix vm.clone panic when target VM already exists +- [a97e6168] govc: support sparse backing in vm.disk.change +- [3380cd30] govc: add CNS volume ls and rm commands +- [f9d7bfdf] sts: fix SignRequest bodyhash for non-empty request body +- [7b4e997b] vapi: add WCP support bundle bindings +- [aae78223] vcsim: fix ListView.Modify +- [0e4bce43] Add AuthorizationManager.HasUserPrivilegeOnEntities wrapper +- [81207eab] vim25/xml: sync with Go 1.15 encoding/xml +- [f7170fd2] govc: add find -p flag +- [d49123c9] Add internal.InventoryPath helper +- [b40cdd8a] govc: add storage.policy commands +- [0c5cdd5d] add / remove pci passthrough device for one VM +- [d0111d28] govc: add vm.console -wss flag +- [94bc8497] Add sms generated types and methods +- [e153061f] examples: fix simulator.RunContainer on MacOSX +- [99fe9954] finder: simplify direct use of InventoryPath func +- [3760bd6c] Added Instant Clone feature Resolves: [#1392](https://github.com/vmware/govmomi/issues/1392) +- [86374ea2] govc: support multi value flags in host.esxcli command +- [9cca13ab] vcsim: avoid ViewManager.ModifyListView race +- [156b1cb0] vcsim: add ListView to race test +- [f903d5da] Add ExtendDisk and InflateDisk wrappers to vlsm/object_manager +- [073cc310] Add AttachDisk and DetachDisk wrappers for the virtualMachine object. +- [a0c7e829] vapi: add tags.Manager.GetAttachedTagsOnObjects example +- [378a24c4] Vsan Performance Data Collection API ([#2021](https://github.com/vmware/govmomi/issues/2021)) +- [55f6f952] vcsim: add mechanism for modeling methods +- [69942fe2] vcsim: fix save/load property collection for VmwareDistributedVirtualSwitch +- [fe3becfa] bats: test fixes for running on MacOSX +- [0422a070] Merge branch 'master' into pc/HardwareInfoNotReplicatingInCloning +- [9f12aae4] vapi: add Content Library example +- [33121b87] vcsim: Honoring the instance uuid provided in spec by caller ([#2052](https://github.com/vmware/govmomi/issues/2052)) +- [9a07942b] Setting hardware properties in clone VM spec from template VM +- [ebcfa3d4] govc: add namespace.cluster.ls command +- [11d45e54] vapi: add namespace management client and vcsim support +- [cdc44d5e] vapi: add helper support "/api" endpoint + + +## [Release v0.23.1](https://github.com/vmware/govmomi/compare/v0.23.0...v0.23.1) + +> Release Date: 2020-07-02 + +### 💡 Examples + +- [0bbb6a7d] add property.Collector.Retrieve example + +### 💫 `vcsim` (Simulator) + +- [0697d33f] add HostNetworkSystem.QueryNetworkHint +- [d7f4bba6] use HostNetworkSystem wrapper with -load flag +- [916b12e6] set HostSystem IP in cluster AddHost_Task +- [e63ec002] add PbmQueryAssociatedProfile method + +### ⚠️ BREAKING + +### 📖 Commits + +- [b7add48c] check if config isn't nil before returning an uuid +- [12955a6c] added support for returning array of BaseCnsVolumeOperationResult for QueryVolumeInfo API +- [0697d33f] vcsim: add HostNetworkSystem.QueryNetworkHint +- [a5c9e1f0] Merge branch 'master' into master +- [c14e3bc5] adding in link to OPS +- [d7f4bba6] vcsim: use HostNetworkSystem wrapper with -load flag +- [916b12e6] vcsim: set HostSystem IP in cluster AddHost_Task +- [e63ec002] vcsim: add PbmQueryAssociatedProfile method +- [0bbb6a7d] examples: add property.Collector.Retrieve example + + +## [Release v0.23.0](https://github.com/vmware/govmomi/compare/v0.22.2...v0.23.0) + +> Release Date: 2020-06-11 + +### 💡 Examples + +- [0e4b487e] Fixed error is not logging in example.go +- [c17eb769] add ContainerView.Find + +### 💫 `govc` (CLI) + +- [10c22fd1] support raw object references in import.ova NetworkMapping +- [4f19eb6d] ipath search flag does not require a Datacenter +- [414c548d] support find with -customValue filter +- [0bf0e761] support VirtualApp with -pool flag +- [f1ae45f5] add -version flag to datastore.create command +- [43e4f8c2] add session.login -X flag +- [70b7e1b4] vm.clone ResourcePool is optional when -cluster is specified +- [2c5ff385] add REST support for session.login -cookie flag +- [7d66cf9a] fix host.info CPU usage +- [244a8369] add session.ls -r flag +- [6c68ccf2] add a VM template clone example +- [bb6ae4ab] ignore ManagedObjectNotFound errors in 'find' command +- [210541fe] remove ClientFlag.WithRestClient +- [75e9e80d] do not try to start a VM template +- [667e6fbe] add guest directory upload/download examples +- [167f5d83] add vm.change -uuid flag +- [bcd06cee] enable library.checkout and library.checkin by default +- [6f087ded] avoid truncation in object.collect +- [e9bb4772] add import.spec support for remote URLs +- [692c1008] support optional compute.policy.ls argument +- [814e4e5c] add vm.change '-memory-pin' flag +- [56e878a5] support nested groups in sso.group.update +- [84346733] add content library helpers +- [0ccfd912] add cluster.group.ls -l flag +- [ae84c494] use OutputFlag for import.spec +- [2dda4daa] add library.clone -ovf flag +- [519d302d] fix doc for -g flag (guest id) choices +- [e582cbd1] add object.collect -o flag +- [d2e6b7df] output formatting enhancements +- [e64c2423] add find -l flag +- [4db4430c] save sessions using sha256 ID + +### 💫 `vcsim` (Simulator) + +- [c3fe4f84] CreateSnapshotTask now returns moref in result +- [b0af443c] add lookup ServiceRegistration example +- [34734712] add AuthorizationManager.HasPrivilegeOnEntities +- [228e0a8f] traverse configManager.datastoreSystem in object.save +- [8acac02a] traverse configManager.virtualNicManager in object.save +- [8a4ab564] traverse configManager.networkSystem in object.save +- [4b8a5988] add extraConfigAlias table +- [a0fe825a] add EventHistoryCollector.ResetCollector implementation +- [558747b3] fixes for PowerCLI +- [9ae04495] apply ExtraConfig after devices +- [4286d7cd] add another test/example for DVS host member validation +- [7e24bfcb] validate DVS membership +- [853656fd] fix flaky library subscriber test +- [7426e2fd] avoid panic if ovf:capacityAllocationUnits is not present +- [55599668] support QueryConfigOptionEx GuestId param +- [67d593cc] VM templates do not have a ResourcePool +- [469e11b9] validate session key in TerminateSession method +- [88d298ff] unique MAC address for VM NICs +- [c4f820dd] create vmdk directory if needed +- [488205f0] support VMs with the same name +- [68349a27] support Folder in RelocateVM spec +- [ab1298d5] add guest operations support +- [7ffb9255] add HostStorageSystem support +- [77b31b84] avoid possible panic in UnregisterVM_Task +- [617c18e7] support tags with the same name +- [dfcf9437] add docs on generated inventory names +- [4cfc2905] add support for NSX backed networks + +### ⚠️ BREAKING + +### 📖 Commits + +- [b639ab4c] Update docs for 0.23 release +- [be7742f2] vapi: use header authentication in file Upload/Download +- [50846878] provided examples for vm.clone and host.esxcli +- [aa97c4d3] Add appliance log forwarding config handler and govc verb ([#1994](https://github.com/vmware/govmomi/issues/1994)) +- [7cdad997] Finder: support DistributedVirtualSwitch traversal +- [10c22fd1] govc: support raw object references in import.ova NetworkMapping +- [c3fe4f84] vcsim: CreateSnapshotTask now returns moref in result +- [4f19eb6d] govc: ipath search flag does not require a Datacenter +- [b0af443c] vcsim: add lookup ServiceRegistration example +- [84f1b733] simulator: fix handling of nil Reference in container walk +- [b5b434b0] Adding sunProfileName in pbm.CapabilityProfileCreateSpec +- [2111324a] providing examples for govc guest.run +- [0eef3b29] Bump to vSphere version 7 +- [b277903e] go binding for CNS QueryVolumeInfo API +- [a048ea52] Move simulator lookupservice registration into ServiceInstance +- [30f1a71a] modify markdown link at simulator.Model +- [7881f541] Add REST session keep alive support +- [3aa9aaba] vapi: sync access to rest.Client.SessionID +- [0a53ac4b] simulator: refactor folder children operations +- [b9152f85] simulator: relax ResourcePool constraint for createVM operation +- [70e9d821] simulator: relax typing condition on RP parent +- [502b7efa] simulator: relax ViewManager typing constraints +- [634fdde1] simulator: remove data race in VM creation flow +- [6eda0169] simulator: protect datastore freespace updates against data races +- [414c548d] govc: support find with -customValue filter +- [487ca0d6] Add logic to return default HealthStatus in CnsCreateVolume. +- [0bf0e761] govc: support VirtualApp with -pool flag +- [f1ae45f5] govc: add -version flag to datastore.create command +- [d0751307] Add support for attach-tag-to-multiple-objects +- [5682b1f2] simulator: relax excessive type assertions in SearchIndex +- [39a4da90] Modify parenthesis for markdown link +- [34734712] vcsim: add AuthorizationManager.HasPrivilegeOnEntities +- [92d464b9] 1. Add retry for CNS Create API with backing disk url 2. Fix binding for CnsAlreadyRegisteredFault +- [235582fe] Add sample test for Create CNS API using backing disk Url path +- [b187863a] 1. Add BackingDiskUrlPath and CnsAlreadyFault go bindings to CNS APIs 2. Update CreateVolume CNS Util to include BackingDiskUrlPath +- [409279fa] Add GetProfileNameByID functionality to PBM +- [228e0a8f] vcsim: traverse configManager.datastoreSystem in object.save +- [8acac02a] vcsim: traverse configManager.virtualNicManager in object.save +- [8a4ab564] vcsim: traverse configManager.networkSystem in object.save +- [43e4f8c2] govc: add session.login -X flag +- [70b7e1b4] govc: vm.clone ResourcePool is optional when -cluster is specified +- [2c5ff385] govc: add REST support for session.login -cookie flag +- [6ccaf303] Add guest.FileManager.TransferURL test +- [03c7611e] Avoid possible nil pointer dereference in guest TransferURL +- [44a78f96] Fix delegated Holder-of-Key token signature +- [11b2aa1a] Update to vSphere 7 APIs +- [4b8a5988] vcsim: add extraConfigAlias table +- [a0fe825a] vcsim: add EventHistoryCollector.ResetCollector implementation +- [558747b3] vcsim: fixes for PowerCLI +- [9ae04495] vcsim: apply ExtraConfig after devices +- [7d66cf9a] govc: fix host.info CPU usage +- [4286d7cd] vcsim: add another test/example for DVS host member validation +- [515621d1] Revert to using sha1 for session cache file names +- [f103a87a] Default to separate session cache directories +- [7e24bfcb] vcsim: validate DVS membership +- [244a8369] govc: add session.ls -r flag +- [6c68ccf2] govc: add a VM template clone example +- [bb6ae4ab] govc: ignore ManagedObjectNotFound errors in 'find' command +- [853656fd] vcsim: fix flaky library subscriber test +- [571f64e7] Fix existing goimport issue +- [7426e2fd] vcsim: avoid panic if ovf:capacityAllocationUnits is not present +- [9e57f983] Add non-null HostLicensableResourceInfo to HostSystem +- [210541fe] govc: remove ClientFlag.WithRestClient +- [75e9e80d] govc: do not try to start a VM template +- [d9220e5d] simulator: add interface for VirtualDiskManager +- [55599668] vcsim: support QueryConfigOptionEx GuestId param +- [67d593cc] vcsim: VM templates do not have a ResourcePool +- [667e6fbe] govc: add guest directory upload/download examples +- [167f5d83] govc: add vm.change -uuid flag +- [bcd06cee] govc: enable library.checkout and library.checkin by default +- [9d4faa6d] Refactor govc session persistence into session/cache package +- [6f087ded] govc: avoid truncation in object.collect +- [7a1fef65] Remove Task from function names in Task struct receiver methods +- [dd839655] Add SetTaskState SetTaskDescription UpdateProgress to object package +- [469e11b9] vcsim: validate session key in TerminateSession method +- [af41ae09] Revert compute policy support +- [ad612b3e] Fix the types of errors returned from VSLM tasks to be their originl vim faults rather than just wrappers of localized error msg +- [9e82230f] Remove extra err check +- [e9bb4772] govc: add import.spec support for remote URLs +- [273aaf71] skip tests when env is not set +- [159c423c] removing usage of spew package +- [76caec95] vapi: prefer header authn to cookie authn +- [6c04cfa0] Dropping fields in entity metadata for 6.7u3 +- [8d15081f] using right version and namespace from sdk/vsanServiceVersions.xml for cns client. making cns/client.go backward compatible to vsan67u3 by dropping unknown elements +- [8dfb29f5] Add nil check for taskInfo result before typecasting CnsVolumeOperationBatchResult +- [d68bbf9b] fixing CnsFault go binding +- [5482bd07] syncing vmodl changes +- [3bcace84] fixing go binding for CnsVolumeOperationResult and CnsFault +- [3c756cbd] Fixing govmomi binding for CNS as per latest VMODL for CnsVsanFileShareBackingDetails. Also fixed cns/client_test.go accordingly. +- [4254df70] Adding new API to get cluster configuration +- [0eacb4ed] removing space before omitempty tag +- [59ce7e4a] Resolve bug in Simulator regarding BackingObjectDetails +- [6ad7e87d] Change the backingObjectDetails attribute to point to interface BaseCnsBackingObjectDetails +- [601f1ded] Add resize support +- [56049aa4] Updating go binding for vsan fileshare vmodl updates +- [af798c01] Add CnsQuerySelectionNameType and CnsKubernetesEntityType back +- [af2723fd] Add bindings for vSANFS and extend CNS bindings to support file volume +- [4e7b9b00] update taskClientVersion for vsphere 7.0 +- [692c1008] govc: support optional compute.policy.ls argument +- [a7d4a77d] Modified return type for Get policy +- [4007484e] Compute Policy support +- [88d298ff] vcsim: unique MAC address for VM NICs +- [814e4e5c] govc: add vm.change '-memory-pin' flag +- [de8bcf25] reset all for recursive calls fix format error +- [57efe91f] Fixed ContainerView.RetrieveWithFilter fetch all specs if empty list of properties given +- [5af5ac8d] Avoid possible panic in Filter.MatchProperty +- [85889777] Add vAPI create binding for compute policy +- [56e878a5] govc: support nested groups in sso.group.update +- [6f46ef8a] Added prefix toggle parameter to govc export.ovf +- [6d3196e4] Disk mode should override default value in vm.disk.attach +- [4be7a425] Replaced ClassOvfParams with ClassDeploymentOptionParams +- [c4f820dd] vcsim: create vmdk directory if needed +- [1ab6fe09] Add Content Library subscriptions support +- [488205f0] vcsim: support VMs with the same name +- [68349a27] vcsim: support Folder in RelocateVM spec +- [6a6a7875] Update CONTRIBUTING to have more info about running CI tests, checks. +- [a73c0d4f] Expose Soap client default transport (a.k.a. its http client default transport) +- [84346733] govc: add content library helpers +- [a225a002] build(deps): bump nokogiri from 1.10.4 to 1.10.8 in /gen +- [b4395d65] Avoid ServiceContent requirement in lookup.NewClient +- [c1e828cb] fix blog links +- [863430ba] toolbox: bump test VM memory for current CoreOS release +- [0ccfd912] govc: add cluster.group.ls -l flag +- [1af6ec1d] Add Namespace support to UseServiceVersion +- [ab1298d5] vcsim: add guest operations support +- [0e4b487e] examples: Fixed error is not logging in example.go +- [f36e13fc] Add Content Library item copy support +- [7ffb9255] vcsim: add HostStorageSystem support +- [ae84c494] govc: use OutputFlag for import.spec +- [2dda4daa] govc: add library.clone -ovf flag +- [77b31b84] vcsim: avoid possible panic in UnregisterVM_Task +- [519d302d] govc: fix doc for -g flag (guest id) choices +- [617c18e7] vcsim: support tags with the same name +- [e582cbd1] govc: add object.collect -o flag +- [0c6eafc1] Apply gomvomi vim25/xml changes +- [4da54375] Simplify ObjectName method +- [d2e6b7df] govc: output formatting enhancements +- [dfcf9437] vcsim: add docs on generated inventory names +- [e64c2423] govc: add find -l flag +- [4db4430c] govc: save sessions using sha256 ID +- [4cfc2905] vcsim: add support for NSX backed networks +- [c17eb769] examples: add ContainerView.Find +- [36056ae6] Import golang/go/src/encoding/xml v1.13.6 +- [346cf59a] Avoid encoding/xml import +- [9cbe57db] fix simulator disk manager fault message. +- [7f685c23] Add permissions for NoCryptoAdmin + + +## [Release v0.22.2](https://github.com/vmware/govmomi/compare/v0.22.1...v0.22.2) + +> Release Date: 2020-02-13 + +### ⚠️ BREAKING + +### 📖 Commits + +- [e7df0c11] Avoid ServiceContent requirement in lookup.NewClient + + +## [Release v0.22.1](https://github.com/vmware/govmomi/compare/v0.22.0...v0.22.1) + +> Release Date: 2020-01-13 + +### ⚠️ BREAKING + +### 📖 Commits + +- [da368950] Release version 0.22.1 +- [a62b12cf] Fix AttributeValue.C14N for 6.7u3 +- [c3d102b1] Add finder example for MultipleFoundError +- [802e5899] vapi: add CreateTag example +- [15630b90] vapi: Add cluster modules client and simulator + + +## [Release v0.22.0](https://github.com/vmware/govmomi/compare/v0.21.0...v0.22.0) + +> Release Date: 2020-01-10 + +### 💡 Examples + +- [72b1cd92] output VM names in performance example +- [f4b3cda7] add Common.Rename +- [dab4ab0d] add VirtualMachine.Customize +- [1828eee9] add VirtualMachine.CreateSnapshot +- [6ff7040e] fix flag parsing +- [cad9a8e2] add ExampleVirtualMachine_Reconfigure + +### 💫 `govc` (CLI) + +- [aed39212] guest -i flag only applies to ProcessManager +- [704b335f] add 5.0 to vm.create hardware version map +- [965109ae] guest.run improvements +- [ee28fcfd] add vm.customize multiple IP support +- [68b3ea9f] fix library.info output formatting +- [5bb7f391] add optional library.info details +- [d8ac7e51] handle xsd:string responses +- [31d3e357] add library.info details +- [182c84a3] fixup tasks formatting +- [08fb2b02] remove guest.run toolbox dependency +- [a727283f] default to simple esxcli format when hints fields is empty +- [204af3c5] add datacenter create/delete examples +- [f6c57ee7] fix vm.create doc regarding -on flag +- [8debfcc3] add device.boot -secure flag +- [2bb2a6ed] add doc on vm.info -r flag +- [e50368c6] avoid env for -cluster placement flag +- [f16eb276] add default library.create thumbprint +- [d8325f34] add thumbprint flag to library.create +- [0bad2bc2] add vm.power doc +- [45d322ea] support vm.customize without a managed spec +- [0a058e0f] fixup usage suggestions +- [3185f7bc] add vm.customize command +- [1b159e27] fix datacenter.info against nested folders +- [149ba7ad] add vm.change -latency flag +- [c35a532d] validate moref argument +- [3fb02b52] add guest.df command + +### 💫 `vcsim` (Simulator) + +- [198b97ca] propagate VirtualMachineCloneSpec.Template +- [168a6a04] add -trace-file option +- [32eeeb24] Get IP address on non-default container network +- [1427d581] avoid possible panic in VirtualMachine.Destroy_Task +- [067d58be] automatically set Context.Caller +- [9e8e9a5a] remove container volumes +- [6cc814b8] bind mount BIOS UUID DMI files +- [9aec1386] validate VirtualDisk UnitNumber +- [d7e43b4e] add Floppy Drive support to OVF manager +- [8646dace] properly initialize portgroup portKeys field +- [286bd5e9] add vim25 client helper to vapi simulator +- [c3163247] use VMX_ prefix for guestinfo env vars +- [a3a09c04] don't allow duplicate names for Folder/StoragePod +- [a0a2296e] pass guestinfo vars as env vars to container vms +- [903fe182] add CustomizationSpecManager support +- [eda6bf3b] simplify container vm arguments input +- [0ce9b0a1] update docs +- [7755fbda] add record/playback functionality +- [fe000674] add VirtualMachine.Rename_Task support +- [d87cd5ac] add feature examples +- [2cc33fa8] Ensure that extraConfig from clone spec is added to VM being cloned +- [70ad060e] use exported response helpers in vapi/simulator +- [1e7aa6c2] avoid ViewManager.ViewList +- [9b0db1c2] avoid race in ViewManager +- [28b5fc6c] use TLS in simulator.Run +- [f962095f] rename Example to Run +- [43d69860] add endpoint registration mechanism +- [c183577b] add PlaceVm support ([#1589](https://github.com/vmware/govmomi/issues/1589)) +- [b17f3a51] DefaultDatastoreID is optional in library deploy + +### ⏮ Reverts + +- [7914609d] gen: retain omitempty field tag with int pointer types + +### ⚠️ BREAKING + +### 📖 Commits + +- [317707be] Update docs for 0.22 release +- [aed39212] govc: guest -i flag only applies to ProcessManager +- [22308123] Clarify DVS EthernetCardBackingInfo error message +- [a1c98f14] Add Content Library synchronization support +- [704b335f] govc: add 5.0 to vm.create hardware version map +- [4e907d99] Clarify System.Read privilege requirement for PortGroup backing +- [554d9284] Fix guest.FileManager.TransferURL cache +- [9b8da88a] Remove toolbox specific guest run implementation +- [965109ae] govc: guest.run improvements +- [ee28fcfd] govc: add vm.customize multiple IP support +- [40001828] Add OVF properties to library deploy ([#1755](https://github.com/vmware/govmomi/issues/1755)) +- [68b3ea9f] govc: fix library.info output formatting +- [198b97ca] vcsim: propagate VirtualMachineCloneSpec.Template +- [5bb7f391] govc: add optional library.info details +- [2509e907] Added the missing RetrieveSnapshotDetails API in VSLM ([#1763](https://github.com/vmware/govmomi/issues/1763)) +- [d8ac7e51] govc: handle xsd:string responses +- [45b3685d] Add library ItemType constants +- [f3e2c3ce] Add retry support for HTTP status codes +- [31d3e357] govc: add library.info details +- [182c84a3] govc: fixup tasks formatting +- [08fb2b02] govc: remove guest.run toolbox dependency +- [b10bcbf3] VSLM: fixed the missing param in the QueryChangedDiskArea API impl +- [168a6a04] vcsim: add -trace-file option +- [72b1cd92] examples: output VM names in performance example +- [32eeeb24] vcsim: Get IP address on non-default container network +- [f9f69237] Move to cs.identity service type for sso admin endpoint +- [1427d581] vcsim: avoid possible panic in VirtualMachine.Destroy_Task +- [067d58be] vcsim: automatically set Context.Caller +- [a727283f] govc: default to simple esxcli format when hints fields is empty +- [08adb5d6] Move to cs.identity service type for sts endpoint +- [9e8e9a5a] vcsim: remove container volumes +- [6cc814b8] vcsim: bind mount BIOS UUID DMI files +- [e793289c] Content Library: add CheckOuts support +- [66c9b10c] Content Library: VM Template support +- [f4b3cda7] examples: add Common.Rename +- [19a726f7] Pass vm.Config.Uuid into the "VM" container via an env var +- [204af3c5] govc: add datacenter create/delete examples +- [dab4ab0d] examples: add VirtualMachine.Customize +- [f6c57ee7] govc: fix vm.create doc regarding -on flag +- [8debfcc3] govc: add device.boot -secure flag +- [9aec1386] vcsim: validate VirtualDisk UnitNumber +- [7914609d] Revert "gen: retain omitempty field tag with int pointer types" +- [9b2c5cc6] Add CustomizationSpecManager.Info method and example +- [d7e43b4e] vcsim: add Floppy Drive support to OVF manager +- [0bf21ec2] Implement some missing methods ("*All*" variants) on SearchIndex MOB +- [2bb2a6ed] govc: add doc on vm.info -r flag +- [8646dace] vcsim: properly initialize portgroup portKeys field +- [e50368c6] govc: avoid env for -cluster placement flag +- [91b1e0a7] Add ability to set DVS discovery protocol on create and change +- [1e130141] Move to Go 1.13 +- [f16eb276] govc: add default library.create thumbprint +- [d8325f34] govc: add thumbprint flag to library.create +- [62c20113] Fix hostsystem ManagementIPs call +- [c4a3908f] Update DVS change to use finder.Network for a single object +- [ee6fe09d] Fix usage instructions +- [5e6f5e3f] gen: retain omitempty field tag with int pointer types +- [286bd5e9] vcsim: add vim25 client helper to vapi simulator +- [841386f1] Add ability to change a vnic on a host +- [391dd80b] Add ability to change the MTU on a DVS that has already been created +- [26a45d61] Change MTU param to use flags.NewInt32 as the type +- [dbcfc3a8] Add MTU flag for DVS creation +- [0399353f] Generate pointer type for ResourceReductionToToleratePercent +- [3f6b8ef5] Add nil checks for all HostConfigManager references +- [c3163247] vcsim: use VMX_ prefix for guestinfo env vars +- [5381f171] Add option to follow all struct fields in mo.References +- [04e4835c] Refactor session KeepAlive tests to use vcsim +- [7391c241] Avoid possible deadlock in KeepAliveHandler +- [41422ea4] build(deps): bump nokogiri from 1.6.3.1 to 1.10.4 in /gen +- [a3a09c04] vcsim: don't allow duplicate names for Folder/StoragePod +- [4c72d2e9] Add a method to update ports on a distributed virtual switch +- [0bad2bc2] govc: add vm.power doc +- [45d322ea] govc: support vm.customize without a managed spec +- [0a058e0f] govc: fixup usage suggestions +- [a0a2296e] vcsim: pass guestinfo vars as env vars to container vms +- [903fe182] vcsim: add CustomizationSpecManager support +- [eda6bf3b] vcsim: simplify container vm arguments input +- [0ce9b0a1] vcsim: update docs +- [c538d867] adding managed obj type to table +- [3185f7bc] govc: add vm.customize command +- [b2a7b47e] Include object.save directory in output +- [e8281f87] Initial support for hybrid Model.Load +- [7755fbda] vcsim: add record/playback functionality +- [8a3fa4f2] set stable vsan client version +- [9eaac5cb] Avoid empty principal in HoK token request +- [4a8da68d] Allow sending multiple characters through -c and name the keys +- [3e3d3515] add simple command list filter +- [fe000674] vcsim: add VirtualMachine.Rename_Task support +- [9166bbdb] support two tags with the same name +- [344653c1] added log type and password scrubber +- [d87cd5ac] vcsim: add feature examples +- [30fc2225] Report errors when cdrom.insert fails +- [a94f2d3a] vslm: fix to throw errors on tasks that are completed with error state +- [37054f03] added IsTemplate vm helper +- [d7aeb628] Fix object.collect with moref argument +- [0765aa63] add GetInventoryPath to NetworkReference interface +- [9fb975b0] Fix description of vm.keystrokes +- [234aaf53] vapi: support DeleteLibrary with subscribed libraries +- [2cc33fa8] vcsim: Ensure that extraConfig from clone spec is added to VM being cloned +- [70ad060e] vcsim: use exported response helpers in vapi/simulator +- [b069efc0] vapi: refactor for external API implementations +- [1e7aa6c2] vcsim: avoid ViewManager.ViewList +- [9b0db1c2] vcsim: avoid race in ViewManager +- [bd298f43] a failing testcase that triggers with -race test +- [03422dd2] vapi: expand internal path constants +- [d296a5f8] Support HoK tokens with Interactive Users +- [c6226542] Fix error check in session.Secret +- [28b5fc6c] vcsim: use TLS in simulator.Run +- [f9b4bb05] Replace LoadRetrievePropertiesResponse with LoadObjectContent +- [d84679eb] Add VirtualHardwareSection.StorageItem +- [a23a5cb1] Check whether there's a NIC before updating guest.ipAddress +- [8a069c27] Add interactiveSession flag +- [25526b21] vm.keystrokes -s (Allow spaces) +- [1828eee9] examples: add VirtualMachine.CreateSnapshot +- [ca3763e7] vapi: return info with current session query +- [f962095f] vcsim: rename Example to Run +- [43d69860] vcsim: add endpoint registration mechanism +- [1b159e27] govc: fix datacenter.info against nested folders +- [c183577b] vcsim: add PlaceVm support ([#1589](https://github.com/vmware/govmomi/issues/1589)) +- [3e71d6be] Add ResourcePool.Owner method +- [b17f3a51] vcsim: DefaultDatastoreID is optional in library deploy +- [68980704] Update generated code to vSphere 6.7u3 +- [7416741c] Add VirtualMachine.QueryChangedDiskAreas(). +- [8ef87890] Content library: support library ID in Finder +- [e373feb8] Add option to propagate MissingSet faults in property.WaitForUpdates +- [6ff7040e] examples: fix flag parsing +- [149ba7ad] govc: add vm.change -latency flag +- [c35a532d] govc: validate moref argument +- [54df157b] Add content library subscription support +- [b86466b7] Fix deadlock for keep alive handlers that attempt log in +- [9ad64557] CNS go bindings +- [9de3b854] Add simulator.Model.Run example +- [4285b614] Include url in Client.Download error +- [caf0b6b3] vcsa: update to 6.7 U3 +- [7ac56b64] Update vcsim Readme.md +- [48ef35df] Update README.md +- [a40837d8] Use gnu xargs in bats tests on Darwin +- [51ad97e1] Add FetchCapabilityMetadata method to Pbm client +- [d124bece] Add v4 option to VirtualMachine.WaitForIP +- [a5a429c0] Add support for the cis session get method +- [4513735f] Don't limit library.Finder to local libraries +- [cad9a8e2] examples: add ExampleVirtualMachine_Reconfigure +- [3fb02b52] govc: add guest.df command + + +## [Release v0.21.0](https://github.com/vmware/govmomi/compare/v0.20.3...v0.21.0) + +> Release Date: 2019-07-24 + +### 💡 Examples + +- [9495f0d8] add CustomFieldManager.Set + +### 💫 `govc` (CLI) + +- [fa755779] support library paths in tags.attach commands +- [2ddfb86b] add datastore.info -H flag +- [b3adfff2] add sso.group commands +- [b5372b0c] host.vnic.info -json support +- [4c41c167] add context to LoadX509KeyPair error +- [910dac72] add vm.change hot-add options +- [746c314e] change logs.download -default=false +- [05f946d4] increase guest.ps -X poll interval +- [cc10a075] add -options support to library.deploy +- [fe372923] rename vcenter.deploy to library.deploy +- [436d7a04] move library.item.update commands to library.session +- [e6514757] consolidate library commands +- [f8249ded] export Archive Path field +- [d2ab2782] add vm.change vpmc-enabled flag +- [e7b801c6] fix vm.change against templates +- [8a856429] fix option.set for int32 type values +- [81391309] add datastore.maintenance.{enter,exit} commands +- [18cb9142] FCD workarounds +- [665affe5] add datastore.cluster.info Description +- [7b7f2013] add permission.remove -f flag + +### 💫 `vcsim` (Simulator) + +- [774f3800] add support to override credentials +- [ecd7312b] fix host uuid +- [c25c41c1] use stable UUIDs for inventory objects +- [1345eeb8] Press any key to exit +- [ee14bd3d] Update NetworkInfo.Portgroup in simulator +- [5b5eaa70] remove httptest.serve flag +- [20c1873e] add library.deploy support +- [0b1ad552] add ovf manager +- [6684016f] fork httptest server package +- [48c1e0a5] add content library support +- [8543ea4f] set guest.toolsRunningStatus property + +### ⚠️ BREAKING + +### 📖 Commits + +- [a0fef816] Update docs for 0.21 release +- [a38f6e87] Content library related cleanups +- [e4024e9c] Fix library AddLibraryItemFileFromURI fingerprint +- [fa755779] govc: support library paths in tags.attach commands +- [5e8cb495] Fixed type bug in global_object_manager Task.QueryResult +- [4a67dc73] govcsim: Support Default UplinkTeamingPolicy in DVSPG +- [9da2362d] Added missing field in VslmExtendDisk_Task in ExtendDisk method +- [91377d77] Add Juju to projects using govmomi +- [f9026a84] VSLM FCD Global Object Manager client for 6.7U2+ +- [9495f0d8] examples: add CustomFieldManager.Set +- [bb170705] govcsim: Create datastore as accessible +- [35d0b7d3] Set the InventoryPath of the folder object in DefaultFolder ([#1515](https://github.com/vmware/govmomi/issues/1515)) +- [2d13a357] Add govmomi performance example +- [2ddfb86b] govc: add datastore.info -H flag +- [55da29e5] govcsim: Set datastore status as normal +- [600e9f7c] Add various govmomi client examples +- [5cccd732] Add http source support to library.import +- [99dd5947] Goreleaser update for multiple archives +- [b3adfff2] govc: add sso.group commands +- [5889d091] tags API: add methods for association of multiple tags/objects +- [b5372b0c] govc: host.vnic.info -json support +- [9b7688e0] Add method that sets vim version to the endpoint service version +- [fe3488f5] Fix tls config in soap.NewServiceClient +- [4c41c167] govc: add context to LoadX509KeyPair error +- [d7430825] Support external PSC lookup service +- [774f3800] vcsim: add support to override credentials +- [47c9c070] Fix HostNetworkSystem.QueryNetworkHint return value +- [910dac72] govc: add vm.change hot-add options +- [4606125e] Fix json request tracing +- [746c314e] govc: change logs.download -default=false +- [05f946d4] govc: increase guest.ps -X poll interval +- [77cb9df5] Add library export support +- [cc10a075] govc: add -options support to library.deploy +- [ecd7312b] vcsim: fix host uuid +- [c25c41c1] vcsim: use stable UUIDs for inventory objects +- [322d9629] Fix pbm field type lookup +- [1345eeb8] vcsim: Press any key to exit +- [a4f58ac6] Update examples to use examples.Run method +- [a31db862] Add permanager example +- [384b1b95] Fix port signature in REST endpoint token auth +- [c222666f] Default to running against vcsim in examples +- [199e737b] Add generated vslm types and methods +- [ee14bd3d] vcsim: Update NetworkInfo.Portgroup in simulator +- [dc631a2d] Format import statement +- [f133c9e9] Fix paths in vsan/methods +- [d8e7cc75] Update copy rights +- [62412641] Add vsan bindings +- [fc3f0e9d] Support resignature of vmfs snapshots ([#1442](https://github.com/vmware/govmomi/issues/1442)) +- [fe372923] govc: rename vcenter.deploy to library.deploy +- [436d7a04] govc: move library.item.update commands to library.session +- [e6514757] govc: consolidate library commands +- [f8249ded] govc: export Archive Path field +- [8a823c52] vcsa: bump to 6.7u2 +- [5b5eaa70] vcsim: remove httptest.serve flag +- [466dc5b2] Update to vSphere 6.7u2 API +- [e9f80882] Add error check to VirtualMachine.WaitForNetIP +- [5611aaa2] Add ovftool support +- [20c1873e] vcsim: add library.deploy support +- [0b1ad552] vcsim: add ovf manager +- [d2ab2782] govc: add vm.change vpmc-enabled flag +- [e7b801c6] govc: fix vm.change against templates +- [8a856429] govc: fix option.set for int32 type values +- [9155093e] Typo and->an +- [81391309] govc: add datastore.maintenance.{enter,exit} commands +- [1a857b94] Add support to reconcile FCD datastore inventory +- [18cb9142] govc: FCD workarounds +- [499a8828] Fix staticcheck issues value of `XXX` is never used +- [665affe5] govc: add datastore.cluster.info Description +- [546e8897] Add error check for deferred functions +- [367c8743] Fix bug with multiple tags in category +- [7b7f2013] govc: add permission.remove -f flag +- [87bc0c85] Makefile: Fix govet target using go1.12 +- [791e5434] travis.yml: Update from golang 1.11 to 1.12 +- [a86a42a2] travis.yml: Update from Ubuntu Trusty to Xenial +- [d92ee75e] Report local Datastore back as type OTHER +- [6684016f] vcsim: fork httptest server package +- [48c1e0a5] vcsim: add content library support +- [69faa2de] Make PostEvent TaskInfo param optional +- [608ad29f] Omit namespace tag in generated method body response types +- [a7c03228] Fix codespell issues +- [728e77db] Fix a race in NewServer(). +- [8543ea4f] vcsim: set guest.toolsRunningStatus property +- [e3143407] Fix elseif gocritic issues +- [89b53312] Fix gocritic emptyStringTest issues +- [63ba9232] Fix some trivial gocritic issues +- [0b8d0ee7] simulator/host_datastore_browser.go: remove commented out code +- [6c17d66c] Fix some staticcheck issues +- [d45b5f34] Fix some gosimple issues +- [90e501a6] Correct the year in the govc changelog +- [8082a261] Update XDR to use fork +- [e94ec246] govc/USAGE.md: Update documentation +- [3fde3319] snapshot.tree: Show snapshots description +- [1d6f743b] Fix year in changelog +- [39b2c871] support customize vm folder in ovf deploy +- [3ad203d3] Use rest.Client for library uploads +- [5d24c38c] lib/finder: Support filenames with "/" +- [087f09f9] govc library: use govc/flags for Datastore and ResourcePool +- [d1a7f491] Remove nested progress.Tee usage +- [7312711e] govc/vm/*: Fix some gosec Errors unhandled issues +- [88601bb7] vcsim/*: Fix Errors unhandled issues +- [61d04b46] session/*: Fix Errors unhandled issues +- [f9a22349] vmdk/*: Fix gosec Errors unhandled issues +- [ca9b71a9] Fix gosec Expect directory permissions to be 0750 or less issues +- [6083e891] Fix gosec potential file inclusion via variable issues +- [38091bf8] Build changes needed for content library +- [885d4b44] Content library additions/finder +- [3fb72d1a] Add support for content library +- [64f2a5ea] Fix API Version check. +- [718331e3] govc/*: Fix some staticcheck issues +- [ba7923ae] Fix all staticcheck "error strings should not be capitalized" issues +- [ed32a917] simulator/*: Fix some staticcheck issues +- [f71d4efb] govc/vm/*: Fix staticcheck issues +- [3d77e2b1] vim25/*: Fix staticcheck issues +- [d711005a] .gitignore: add editor files *~ +- [43ff04f1] Fix [#1173](https://github.com/vmware/govmomi/issues/1173) +- [562aa0db] Go Mod Support + + +## [Release v0.20.3](https://github.com/vmware/govmomi/compare/v0.20.2...v0.20.3) + +> Release Date: 2019-10-08 + +### ⚠️ BREAKING + +### 📖 Commits + +- [fdd27786] Fix tls config in soap.NewServiceClient + + +## [Release v0.20.2](https://github.com/vmware/govmomi/compare/v0.20.1...v0.20.2) + +> Release Date: 2019-07-03 + +### ⚠️ BREAKING + +### 📖 Commits + +- [bd9cfd18] Set the InventoryPath of the folder object in DefaultFolder ([#1515](https://github.com/vmware/govmomi/issues/1515)) + + +## [Release v0.20.1](https://github.com/vmware/govmomi/compare/v0.20.1-vsan-65a0d6ab...v0.20.1) + +> Release Date: 2019-05-20 + +### ⚠️ BREAKING + +### 📖 Commits + +- [4514987f] Fix port signature in REST endpoint token auth + + +## [Release v0.20.1-vsan-65a0d6ab](https://github.com/vmware/govmomi/compare/v0.20.1-vsan-199e737b...v0.20.1-vsan-65a0d6ab) + +> Release Date: 2021-02-19 + +### ⚠️ BREAKING + +### 📖 Commits + +- [536a78e2] Add function to get vsan host config +- [58e6303b] Add test for vsan host config +- [74f25ae7] Adding VsanQueryObjectIdentities and QueryVsanObjects +- [e43fff34] skip tests when env is not set +- [43532740] Adding new API to get cluster configuration +- [9a53dde4] Add CnsQuerySelectionNameType and CnsKubernetesEntityType back +- [bac56c3b] Add bindings for vSANFS and extend CNS bindings to support file volume + + +## [Release v0.20.1-vsan-199e737b](https://github.com/vmware/govmomi/compare/v0.20.0...v0.20.1-vsan-199e737b) + +> Release Date: 2019-05-13 + +### 💫 `govc` (CLI) + +- [fe372923] rename vcenter.deploy to library.deploy +- [436d7a04] move library.item.update commands to library.session +- [e6514757] consolidate library commands +- [f8249ded] export Archive Path field +- [d2ab2782] add vm.change vpmc-enabled flag +- [e7b801c6] fix vm.change against templates +- [8a856429] fix option.set for int32 type values +- [81391309] add datastore.maintenance.{enter,exit} commands +- [18cb9142] FCD workarounds +- [665affe5] add datastore.cluster.info Description +- [7b7f2013] add permission.remove -f flag + +### 💫 `vcsim` (Simulator) + +- [83e068c5] fix ListView.Modify +- [3a6a02c0] add ListView to race test +- [89678493] avoid ViewManager.ModifyListView race +- [3661c9b4] add PlaceVm support ([#1589](https://github.com/vmware/govmomi/issues/1589)) +- [5b5eaa70] remove httptest.serve flag +- [20c1873e] add library.deploy support +- [0b1ad552] add ovf manager +- [6684016f] fork httptest server package +- [48c1e0a5] add content library support +- [8543ea4f] set guest.toolsRunningStatus property + +### ⚠️ BREAKING + +### 📖 Commits + +- [b3c1d778] Add generated vslm types and methods +- [67f65ce0] Remove duplicate cns bindings from vsan directory +- [42ba0d6e] Add test for vsan host config +- [45e77063] Add function to get vsan host config +- [668f7bcb] Add wrappers for retrieving vsan properties +- [001df6f8] Use gofmt +- [f51a8ca4] Add vSAN 7.0 API bindings +- [f08fb2a3] Add vSAN 7.0 API bindings +- [6eec064a] Adding VsanQueryObjectIdentities and QueryVsanObjects +- [d17598e4] Vsan Performance Data Collection API ([#2021](https://github.com/vmware/govmomi/issues/2021)) +- [7406f2dc] skip tests when env is not set +- [c32d3619] removing usage of spew package +- [e247d675] Adding new API to get cluster configuration +- [65160c8e] Add CnsQuerySelectionNameType and CnsKubernetesEntityType back +- [2b954493] Add bindings for vSANFS and extend CNS bindings to support file volume +- [6e27e035] Merge branch 'topic/georgek/cherrypick' into 'vmware-internal' +- [83e068c5] vcsim: fix ListView.Modify +- [3a6a02c0] vcsim: add ListView to race test +- [89678493] vcsim: avoid ViewManager.ModifyListView race +- [86ad2937] Merge branch 'topic/desaiy/vmware-internal' into 'vmware-internal' +- [79a6eb29] Add ExtendDisk and InflateDisk wrappers to vlsm/object_manager +- [6e531650] Add AttachDisk and DetachDisk wrappers for the virtualMachine object. +- [599c291f] Merge branch 'faiyaza/vmware-internal' into 'vmware-internal' +- [5ff5d327] Update to vSphere 7 APIs +- [c41c4577] Update generated code to vSphere 6.7u3 +- [4b803b94] Update to vSphere 6.7u2 API +- [51cd0cee] adds error check before returning value +- [3088c640] adds code to query for license description +- [77932350] adds client code to add license description spec +- [da94d023] Merge branch 'topic/rvembuli/fix_client_method' into 'vmware-internal' +- [1a4b19ad] adds error check before returning value +- [95605ad3] Merge branch 'topic/rvembuli/add_product_search' into 'vmware-internal' +- [29b5b751] adds code to query for license description +- [38855369] Merge branch 'topic/rvembuli/2590835/add_client_dlf' into 'vmware-internal' +- [1c8979ee] adds client code to add license description spec +- [aeafc880] Merge branch 'topic/rvembuli/update_bindings_license_service' into 'vmware-internal' +- [56e5babf] adds client bindings generated from wsdl file in http://build-squid.eng.vmware.com/build/mts/release/sb-37722446/publish/wsdl/license-cis-vmodl-bindings.wsdl +- [6a920510] Merge branch 'topic/nmadanapalli/ls-persistent-client-PR2594868' into 'vmware-internal' +- [5eb03816] Keepalive handling for ls.Client +- [9901834a] Merge branch 'topic/nmadanapalli/ls-cookie-PR2591635' into 'vmware-internal' +- [57a072fb] Instantiating a new cookie jar for every LS client instance +- [01cf5cca] Merge branch 'topic/faiyaza/guestopscherrypick' into 'vmware-internal' +- [97012c79] Avoid possible nil pointer dereference in guest TransferURL +- [a8ed5502] Merge branch 'topic/nmadanapalli/license-asset-bindings' into 'vmware-internal' +- [876137ae] Adding AssetService bindings +- [2407e148] Merge branch 'topic/nmadanapalli/backport-322d962' into 'vmware-internal' +- [9c89ff53] Fix pbm field type lookup +- [7e26d088] Merge branch 'cherry-pick-a355f576' into 'vmware-internal' +- [80c6a727] Switch VAPI cluster modules to using NewResource to fix URLs to start with /rest/vcenter/ +- [e4872724] Local cherry-pick of Cluster Module API support without simulator testing. +- [94f7310e] Merge branch 'topic/pradyumnaa/nsxt-status' into 'vmware-internal' +- [b1c7b0f3] Add the NsxtStatus field to HostProxySwitch +- [fd246c9e] Merge branch 'topic/mansia/license' into 'vmware-internal' +- [8d40f673] Enhance govmomi license bindings to accept null NotificationSearchSpec +- [c07aa445] Merge branch 'topic/ljoyce/lifecycle-managed' into 'vmware-internal' +- [f9c0e4fb] Add lifecycleManaged property to ComputeResource object +- [6f8ae93b] Cherry-pick 62c20113 and b916904 +- [dcd17fc6] Merge branch 'topic/mansia/license' into 'vmware-internal' +- [1f5c0b19] Add cis.license client +- [fa03c5db] Merge branch 'cherry-pick-97c24006' into 'vmware-internal' +- [a2c9e16e] Merge branch 'cherry-pick-674286cb' into 'vmware-internal' +- [318eaf6d] Add support for appliance/logging/forwarding VAPI [1/3] +- [ffcb0eca] Merge branch 'cherry-pick-d296a5f8' into 'vmware-internal' +- [00e53090] Support HoK tokens with Interactive Users +- [f71af4d0] Merge branch 'cherry-pick-c183577b' into 'vmware-internal' +- [3661c9b4] vcsim: add PlaceVm support ([#1589](https://github.com/vmware/govmomi/issues/1589)) +- [c81eab04] Merge branch 'cherry-pick-384b1b95' into 'vmware-internal' +- [2751a42a] Fix port signature in REST endpoint token auth +- [25117583] Merge branch 'topic/anubhabm/wcp-license' into 'vmware-internal' +- [44d91635] Adding API bindings for isFeatureAvailable internal API +- [5f837dc8] Added support for HostSystem InternalConfigManager property +- [d7abbdbb] Add bindings for NetworkSystem.PerformHostOpaqueNetworkDataOperation to vim25 +- [4f441128] Merge branch 'topic/echu/cis-session-get' into 'vmware-internal' +- [a3ba80dc] cherry-pick cis-session-get change from master +- [aba0bbae] Add vAPI create binding for compute policy +- [fe292fa4] Add vAPI create binding for compute policy +- [c64008ad] Always use the service version when possible. +- [9ff64cfe] Add method that sets vim version to the endpoint service version +- [218f7ef5] Add TenantManager helper +- [ce5f283c] Fix deadlock for keep alive handlers that attempt log in +- [3c702b66] Add TenantManager bindings to vim25 +- [a6b86c92] Adding API bindings for scalable shares +- [16823c9b] Adding API bindings for createNamespaceFolder and createNamespaceResourcePool internal APIs +- [fe42604f] Pulling changes from master and resolving conflicts +- [dc631a2d] Format import statement +- [f133c9e9] Fix paths in vsan/methods +- [d8e7cc75] Update copy rights +- [62412641] Add vsan bindings +- [605b62fa] Adding bindings for placeMultiVms API +- [fc3f0e9d] Support resignature of vmfs snapshots ([#1442](https://github.com/vmware/govmomi/issues/1442)) +- [fe372923] govc: rename vcenter.deploy to library.deploy +- [436d7a04] govc: move library.item.update commands to library.session +- [e6514757] govc: consolidate library commands +- [1445cab3] Merge branch 'cherry-pick-0b097847' into 'vmware-internal' +- [ee087144] Added SphereletManager bindings +- [f8249ded] govc: export Archive Path field +- [8a823c52] vcsa: bump to 6.7u2 +- [5b5eaa70] vcsim: remove httptest.serve flag +- [e9f80882] Add error check to VirtualMachine.WaitForNetIP +- [5611aaa2] Add ovftool support +- [20c1873e] vcsim: add library.deploy support +- [0b1ad552] vcsim: add ovf manager +- [d2ab2782] govc: add vm.change vpmc-enabled flag +- [e7b801c6] govc: fix vm.change against templates +- [8a856429] govc: fix option.set for int32 type values +- [9155093e] Typo and->an +- [81391309] govc: add datastore.maintenance.{enter,exit} commands +- [1a857b94] Add support to reconcile FCD datastore inventory +- [18cb9142] govc: FCD workarounds +- [499a8828] Fix staticcheck issues value of `XXX` is never used +- [665affe5] govc: add datastore.cluster.info Description +- [546e8897] Add error check for deferred functions +- [367c8743] Fix bug with multiple tags in category +- [7b7f2013] govc: add permission.remove -f flag +- [87bc0c85] Makefile: Fix govet target using go1.12 +- [791e5434] travis.yml: Update from golang 1.11 to 1.12 +- [a86a42a2] travis.yml: Update from Ubuntu Trusty to Xenial +- [d92ee75e] Report local Datastore back as type OTHER +- [6684016f] vcsim: fork httptest server package +- [48c1e0a5] vcsim: add content library support +- [69faa2de] Make PostEvent TaskInfo param optional +- [608ad29f] Omit namespace tag in generated method body response types +- [a7c03228] Fix codespell issues +- [728e77db] Fix a race in NewServer(). +- [8543ea4f] vcsim: set guest.toolsRunningStatus property +- [e3143407] Fix elseif gocritic issues +- [89b53312] Fix gocritic emptyStringTest issues +- [63ba9232] Fix some trivial gocritic issues +- [0b8d0ee7] simulator/host_datastore_browser.go: remove commented out code +- [6c17d66c] Fix some staticcheck issues +- [d45b5f34] Fix some gosimple issues +- [90e501a6] Correct the year in the govc changelog +- [8082a261] Update XDR to use fork +- [e94ec246] govc/USAGE.md: Update documentation +- [3fde3319] snapshot.tree: Show snapshots description +- [1d6f743b] Fix year in changelog +- [39b2c871] support customize vm folder in ovf deploy +- [3ad203d3] Use rest.Client for library uploads +- [5d24c38c] lib/finder: Support filenames with "/" +- [087f09f9] govc library: use govc/flags for Datastore and ResourcePool +- [d1a7f491] Remove nested progress.Tee usage +- [7312711e] govc/vm/*: Fix some gosec Errors unhandled issues +- [88601bb7] vcsim/*: Fix Errors unhandled issues +- [61d04b46] session/*: Fix Errors unhandled issues +- [f9a22349] vmdk/*: Fix gosec Errors unhandled issues +- [ca9b71a9] Fix gosec Expect directory permissions to be 0750 or less issues +- [6083e891] Fix gosec potential file inclusion via variable issues +- [38091bf8] Build changes needed for content library +- [885d4b44] Content library additions/finder +- [3fb72d1a] Add support for content library +- [64f2a5ea] Fix API Version check. +- [718331e3] govc/*: Fix some staticcheck issues +- [ba7923ae] Fix all staticcheck "error strings should not be capitalized" issues +- [ed32a917] simulator/*: Fix some staticcheck issues +- [f71d4efb] govc/vm/*: Fix staticcheck issues +- [3d77e2b1] vim25/*: Fix staticcheck issues +- [d711005a] .gitignore: add editor files *~ +- [43ff04f1] Fix [#1173](https://github.com/vmware/govmomi/issues/1173) +- [562aa0db] Go Mod Support + + +## [Release v0.20.0](https://github.com/vmware/govmomi/compare/v0.19.0...v0.20.0) + +> Release Date: 2019-02-06 + +### 💫 `govc` (CLI) + +- [308dbf99] fix object.collect error for multiple objects with same path +- [4635c1cc] add device name match support to device.ls and device.remove +- [c36eb50f] add vm.disk.attach -mode flag +- [b234cdbc] add category option to relevant tags commands +- [afe5f42d] add vm.create -version option +- [b733db99] fields.set can now add missing fields +- [cad627a6] add fields.info command + +### 💫 `vcsim` (Simulator) + +- [957ef0f7] require authentication in vapi simulator +- [32148187] Resolve issue making device changes on clone (resolves [#1355](https://github.com/vmware/govmomi/issues/1355)) +- [cbb4abc9] fix SearchDatastore task info entity +- [2682c021] add EnvironmentBrowser support +- [3b9a4c9f] avoid zero IP address in GOVC_URL output +- [1921f73a] avoid panic when event template is not defined +- [d79013aa] implement RefreshStorageInfo method for virtual machine +- [69dfdd77] configure HostSystem port +- [bba50b40] datastore.upload now creates missing directories in destination path. +- [d2506759] add option to run container as vm +- [47284860] add SessionIsActive support +- [c5ee00bf] fix fault detail encoding +- [1284300c] support base types in property filter +- [25ae5c67] PropertyCollector should not require PathSet +- [4f1c89e5] allow '.' in vm name +- [b8c04142] populate VM guest.net field +- [223b2a2a] add SearchIndex FindByDnsName support +- [b26e10f0] correct property update in RemoveSnapshotTask +- [693f3fb6] update VM snapshot methods to change VM properties with UpdateObject +- [06e13bbe] support setting vm fields via extraConfig +- [a4330365] update VM configureDevices method to change VM properties with UpdateObject +- [5f8acb7a] update VM device add operation - stricter key generation, new InvalidDeviceSpec condition +- [846ae27a] add PBM support +- [d41d18aa] put VM into registry earlier during CreateVM +- [89b4c2ce] add datastore access check for vm host placement +- [f9f9938e] add task_manager description property templates +- [9bb5bde2] fix defaults when generating vmdk paths +- [0b650fd3] fix custom_fields_manager test +- [588bc224] replace HostSystem template IP with vcsim listen address +- [7066f8dc] Change CustomFieldsManager SetField to use ctx.WithLock and add InvalidArgument fault check. +- [fe070811] update DVS methods to use UpdateObject instead of setting fields directly +- [03939cce] add vslm support +- [c02efc3d] add setCustomValue support +- [94804159] add fault message to PropertyCollector RetrieveProperties +- [36035f5b] add HistoryCollector scrollable view support + +### ⚠️ BREAKING + +### 📖 Commits + +- [da7af247] Fix for govc/build.sh wrong dir +- [90a863be] Update docs for 0.20 release +- [957ef0f7] vcsim: require authentication in vapi simulator +- [32148187] vcsim: Resolve issue making device changes on clone (resolves [#1355](https://github.com/vmware/govmomi/issues/1355)) +- [a7563c4d] Use path id for tag-association requests +- [cbb4abc9] vcsim: fix SearchDatastore task info entity +- [2682c021] vcsim: add EnvironmentBrowser support +- [3b9a4c9f] vcsim: avoid zero IP address in GOVC_URL output +- [b261f25d] Add 2x blog posts about vcsim +- [1921f73a] vcsim: avoid panic when event template is not defined +- [308dbf99] govc: fix object.collect error for multiple objects with same path +- [d79013aa] vcsim: implement RefreshStorageInfo method for virtual machine +- [69dfdd77] vcsim: configure HostSystem port +- [4f50681f] Fix of the missing http body close under soap client upload +- [bba50b40] vcsim: datastore.upload now creates missing directories in destination path. +- [8ac7c5a8] Fixed 64-bit aligment issues with atomic counters +- [7ca12ea2] fix device.info Write output +- [3a82237c] device.ls -json doesn't work for now +- [86f4ba29] ssoadmin:create local group and add users to group ([#1327](https://github.com/vmware/govmomi/issues/1327)) +- [2d8ef2c6] Format with latest version of goimports +- [4635c1cc] govc: add device name match support to device.ls and device.remove +- [d7857a13] Updated the examples for the correct format +- [71e19136] Updated to reflect PR feedback +- [d2506759] vcsim: add option to run container as vm +- [61b7fe3e] Added string support +- [a72a4c42] Initial Support for PutUsbScanCodes +- [47284860] vcsim: add SessionIsActive support +- [c5ee00bf] vcsim: fix fault detail encoding +- [aaf83275] Summary of changes: 1. Changing the pbm client's path as java client is expecting /pbm. 2. Added PbmRetrieveServiceContent method in the unauthorized list. +- [c36eb50f] govc: add vm.disk.attach -mode flag +- [1284300c] vcsim: support base types in property filter +- [25ae5c67] vcsim: PropertyCollector should not require PathSet +- [b234cdbc] govc: add category option to relevant tags commands +- [138f30f8] Makefiles for govc/vcsim; updates govc/build.sh +- [4f1c89e5] vcsim: allow '.' in vm name +- [afe5f42d] govc: add vm.create -version option +- [b8c04142] vcsim: populate VM guest.net field +- [223b2a2a] vcsim: add SearchIndex FindByDnsName support +- [b26e10f0] vcsim: correct property update in RemoveSnapshotTask +- [693f3fb6] vcsim: update VM snapshot methods to change VM properties with UpdateObject +- [e5948f44] build: Refactored Travis-CI to use containers +- [06e13bbe] vcsim: support setting vm fields via extraConfig +- [651d4881] Allow pointer values in mo.ApplyPropertyChange +- [546a7df6] Tags support for First Class Disks +- [a4330365] vcsim: update VM configureDevices method to change VM properties with UpdateObject +- [5f8acb7a] vcsim: update VM device add operation - stricter key generation, new InvalidDeviceSpec condition +- [86375ceb] Merge branch 'master' into fields-info +- [bf962f18] Update govc/fields/add.go +- [98575e0c] Update govc/fields/add.go +- [b733db99] govc: fields.set can now add missing fields +- [cad627a6] govc: add fields.info command +- [ed2a4cff] vm.power: Make waiting for op completion optional +- [846ae27a] vcsim: add PBM support +- [d41d18aa] vcsim: put VM into registry earlier during CreateVM +- [1926071e] Datastore Cluster placement support for First Class Disks +- [89b4c2ce] vcsim: add datastore access check for vm host placement +- [f9f9938e] vcsim: add task_manager description property templates +- [9bb5bde2] vcsim: fix defaults when generating vmdk paths +- [0b650fd3] vcsim: fix custom_fields_manager test +- [588bc224] vcsim: replace HostSystem template IP with vcsim listen address +- [7066f8dc] vcsim: Change CustomFieldsManager SetField to use ctx.WithLock and add InvalidArgument fault check. +- [ef517cae] Display category name instead of ID in govc tags.info +- [d69c9787] goimports updates +- [fe070811] vcsim: update DVS methods to use UpdateObject instead of setting fields directly +- [03939cce] vcsim: add vslm support +- [accb2863] Add vslm package and govc disk commands +- [478ebae6] [doc] add an example for cpu and memory hotplug +- [c02efc3d] vcsim: add setCustomValue support +- [c3c79d16] goimports updates +- [ce71b6c2] vcsa: bump to 6.7.0 U1 +- [94804159] vcsim: add fault message to PropertyCollector RetrieveProperties +- [1ad0d87d] Removed NewWithDelay (not needed anymore) +- [5900feef] Updated documentation +- [5a87902b] Added delay functionality +- [c0518fd2] Add LoginByToken to session KeepAliveHandler +- [e0736431] Update Ansible link in README +- [36035f5b] vcsim: add HistoryCollector scrollable view support +- [bc2636fe] Move govc tags rest.Client helper to ClientFlag +- [54a181af] Add SSO support for vAPI +- [8817c27b] replace * by client's host+port +- [ac898b50] change hostname only if set to * and still set thumbprint +- [7a5cc6b7] replace hostname only if unset + + +## [Release v0.19.0](https://github.com/vmware/govmomi/compare/v0.18.0...v0.19.0) + +> Release Date: 2018-09-30 + +### 💫 `govc` (CLI) + +- [6b4a62b1] fix test case for new cluster.rule.info command +- [1350eea6] add new command cluster.rule.info + +### 💫 `vcsim` (Simulator) + +- [f3260968] add dvpg networks to HostSystem.Parent +- [17352fce] add support for tags API +- [c29d4b12] Logout should not unregister PropertyCollector singleton +- [11fb0d58] add ResetVM and SuspendVM support +- [39e6592d] add support for PropertyCollector incremental updates +- [619fbe28] do not include DVS in HostSystem.Network + +### ⚠️ BREAKING + +### 📖 Commits + +- [3617f28d] Update docs for 0.19 release +- [4316838a] vcsa: bump to 6.7.0d +- [64d875b9] Added PerformanceManager simulator +- [f3260968] vcsim: add dvpg networks to HostSystem.Parent +- [862da065] Allowing the use of STS for exchanging tokens +- [83ce863a] Handle empty file name in import.spec +- [a99f702d] Bump travis golang version from 1.10 to 1.11 +- [e4e8e2d6] Clean up unit test messaging +- [8e04e3c7] Run goimports on go source files +- [2431ae00] Add mailmap for bruceadowns +- [e805b4ea] Updates per dep ensure integration +- [70589fb6] Add ignore of intellij project settings directory +- [d114fa69] Print action for dvs security groups +- [d458266a] fix double err check +- [3f0e0aa7] remove providerSummary cache +- [cf9c16c4] Avoid use of Finder all param in govc +- [c4face4f] Print DVS rules for dvportgroup +- [91a33dd4] Finalize tags API +- [7d54bf9f] README: Fix path to LICENSE.txt file +- [17352fce] vcsim: add support for tags API +- [c29d4b12] vcsim: Logout should not unregister PropertyCollector singleton +- [8bda0ee1] Fix format in test +- [8be5207c] Add test for WaitOption.MaxWaitSeconds == 0 behaviour in simulator +- [900e1a35] Fix the WaitOption.MaxWaitSeconds == 0 behaviour in simulator +- [056ad0d4] vcsa: bump to 6.7.0c release +- [6b4a62b1] govc: fix test case for new cluster.rule.info command +- [1350eea6] govc: add new command cluster.rule.info +- [a05cd4b0] add output in cluster.rule.ls -name for ClusterVmHostRuleInfo and ClusterDependencyRuleInfo rules, add -l Option to cluster.rule.ls +- [11fb0d58] vcsim: add ResetVM and SuspendVM support +- [3e6b2d6e] Add ability to move multiple hosts into a cluster +- [e9f9920f] Add method to move host into cluster +- [39e6592d] vcsim: add support for PropertyCollector incremental updates +- [b7c270c6] Add testing support for govc tags commands +- [619fbe28] vcsim: do not include DVS in HostSystem.Network +- [6b6060dc] show rule details for ClusterVmHostRuleInfo rules in cluster.rule.ls +- [0c28a25d] Use govc find instead of ls to assign licenses +- [c1377063] Only test with Go 1.10 on Travis CI +- [4cfadda5] Avoid panic if fault detail is nil +- [d06874e1] Upgrade for govc tags commands +- [fdfaec9c] Better documentation for VirtualMachine.UUID +- [e1285a03] Add UUID helper for VirtualMachine +- [919b728c] Complete tags management APIs ([#1162](https://github.com/vmware/govmomi/issues/1162)) +- [b3251638] vcsa: bump to 6.7.0a release +- [a1fbb6ef] Optionally check root CAs for validity ([#1154](https://github.com/vmware/govmomi/issues/1154)) +- [add38bed] Fixed govc host.info logical CPU count +- [1ddfb011] Tags Categories cmd available ([#1150](https://github.com/vmware/govmomi/issues/1150)) +- [83ae35fb] default MarkAsTemplate to false in import spec +- [49f0dea7] add option to mark VM as template on OVX import +- [1f9e19f4] example: uniform unit for host memory +- [4cfd1376] fix example output. + + +## [Release v0.18.0](https://github.com/vmware/govmomi/compare/v0.17.1...v0.18.0) + +> Release Date: 2018-05-24 + +### 💫 `govc` (CLI) + +- [b841ae01] import.ovf pool flag should be optional if host is specified +- [f5c84b98] avoid Login() attempt if username is not set +- [d91fcbf4] add json support to find command +- [ba2d2323] fix host.esxcli error handling + +### 💫 `vcsim` (Simulator) + +- [8a5438b0] add STS simulator +- [c0337740] use VirtualDisk CapacityInKB for device summary +- [3d7fbac2] add property collector field type mapping for integer arrays + +### ⚠️ BREAKING + +### 📖 Commits + +- [e4b69fab] Update docs for 0.18 release +- [1dbfb317] Bump versions +- [b841ae01] govc: import.ovf pool flag should be optional if host is specified +- [96a905c1] Add -sharing option to vm.disk.create and vm.disk.attach +- [4b4e2aaa] Add VirtualDiskManager wrapper to set UUID +- [40a565b3] adjust datastore size when vm is added or updated or deleted +- [7f6479ba] update datastore capacity and free space when it is started +- [76dfefd3] Avoid recursive root path search in govc find command +- [623c7fa9] Change key name according to Datacenter object +- [24d0cf1b] added check for `InstanceUuid` when `VmSearch` is true in `FindByUuid` +- [25fc474c] Issue token if needed for govc sso commands +- [822fd1c0] Fixed leading "/" requirement in FindByInventoryPath +- [59d9f6a0] Add devbox scripts +- [fd45d81c] Add -U option to sso.service.ls +- [f5c84b98] govc: avoid Login() attempt if username is not set +- [8a5438b0] vcsim: add STS simulator +- [93f7fbbd] Fix govc vm.clone -annotation flag +- [bcff5383] save CapacityInKB in thousand delimited format +- [db12d4cb] Avoid possible panic in portgroup EthernetCardBackingInfo +- [d120efcb] Add STS support for token renewal +- [76b1ceaf] Add vmxnet2, pcnet32 and sriov to VirtualDeviceList.EthernetCardTypes +- [c0337740] vcsim: use VirtualDisk CapacityInKB for device summary +- [3d7fbac2] vcsim: add property collector field type mapping for integer arrays +- [42b30bb6] Finder.DefaultHostSystem should find hosts in nested folders +- [b8323d6b] Avoid property.Filter matching against unset properties +- [64788667] Update to vSphere 6.7 API +- [d3ae3004] Bump vCenter and ESXi builds to the latest release +- [098fc449] Add ssoadmin client and commands +- [80a9c20e] vm.Snapshot should be 'nil' instead of an empty 'vim.vm.SnapshotInfo' when there are no snapshots +- [1b1b428e] added failing tests for when vm.Snapshot should / shouldn't be 'nil' +- [a34ab4ba] Refactor LoginExtensionByCertificate tunnel usage +- [5b36033f] Lookup Service support +- [3f07eb74] add empty fields, but don't return them in the case of 'RetrievePropertiesEx' +- [05bdabe0] added failing test case for issue 1061 +- [903e8644] SAML token authentication support +- [d91fcbf4] govc: add json support to find command +- [ba2d2323] govc: fix host.esxcli error handling +- [ff687746] Dep Support +- [5f701460] Add -firmware parameter to 'govc vm.create' with values bios|efi + + +## [Release v0.17.1](https://github.com/vmware/govmomi/compare/v0.17.0...v0.17.1) + +> Release Date: 2018-03-19 + +### 💫 `vcsim` (Simulator) + +- [0502ee9b] add Destroy method for Folder and Datacenter types +- [0636dc8c] add EventManager.QueryEvents + +### ⚠️ BREAKING + +### 📖 Commits + +- [123ed177] govc release 0.17.1 +- [24d88451] Avoid possible panic in QueryVirtualDiskInfo +- [82129fb7] Add goreleaser to automate release process +- [ce88b296] Fix dvs.portgroup.info filtering +- [0502ee9b] vcsim: add Destroy method for Folder and Datacenter types +- [1620160d] In progress.Reader emit final report on EOF. +- [0636dc8c] vcsim: add EventManager.QueryEvents + + +## [Release v0.17.0](https://github.com/vmware/govmomi/compare/v0.16.0...v0.17.0) + +> Release Date: 2018-02-28 + +### 💫 `govc` (CLI) + +- [29498644] fix vm.clone to use -net flag when source does not have a NIC +- [d12b8f25] object.collect support for raw filters +- [6cb9fef8] fix host.info CPU usage +- [5786e7d2] add -cluster flag to license.assign command +- [d4ee331c] allow columns in guest login password ([#972](https://github.com/vmware/govmomi/issues/972)) + +### 💫 `vcsim` (Simulator) + +- [d2ba47d6] add simulator.Datastore type +- [937998a1] set VirtualMachine summary.config.instanceUuid +- [1c76c63d] update HostSystem.Summary.Host reference +- [274f3d63] add EventManager support +- [cc21a5ab] stats related fixes +- [fa2bee10] avoid data races +- [ca6f5d1d] respect VirtualDeviceConfigSpec FileOperation +- [7811dfce] avoid keeping the VM log file open +- [828ce5ec] add UpdateOptions support +- [d03f38fa] add session support +- [a3c9ed2b] Add VM.MarkAsTemplate support +- [50735461] more input spec honored in ReConfig VM +- [638d972b] Initialize VM fields properly +- [aa0382c1] Honor the input spec in ReConfig VM +- [42f9a133] Add HostLocalAccountManager +- [76f376a3] workaround xml ns issue with pyvsphere ([#958](https://github.com/vmware/govmomi/issues/958)) +- [45c5269b] add MakeDirectoryResponse ([#938](https://github.com/vmware/govmomi/issues/938)) +- [b4e77bd2] copy RoleList for AuthorizationManager ([#932](https://github.com/vmware/govmomi/issues/932)) +- [2a8a5168] apply vm spec NumCoresPerSocket ([#930](https://github.com/vmware/govmomi/issues/930)) +- [3a61d85f] Configure dvs with the dvs config spec +- [5f0f4004] Add VirtualMachine guest ID validation ([#921](https://github.com/vmware/govmomi/issues/921)) +- [ef571547] add QueryVirtualDiskUuid ([#920](https://github.com/vmware/govmomi/issues/920)) +- [27229ab7] update ServiceContent to 6.5 ([#917](https://github.com/vmware/govmomi/issues/917)) + +### ⚠️ BREAKING + +### 📖 Commits + +- [1d63da8d] govc release 0.17 +- [3017acf8] Print Table of Contents in usage.md Found good example of toc using markdown here: https://stackoverflow.com/a/448929/1572363 +- [ce54fe2c] Fix typo +- [201fc601] Implement Destroy task for HostSystem +- [92ce4244] Init PortKeys in DistributedVirtualPortgroup +- [795f2cc7] Avoid json encoding error in Go 1.10 +- [e805389e] Add 'Type' field to device.info -json output +- [d622f149] Use VirtualDiskManager in datastore cp and mv commands +- [f219bf3b] object: Return correct helper object for OpaqueNetwork +- [29498644] govc: fix vm.clone to use -net flag when source does not have a NIC +- [43c95b21] Fix build on Windows +- [38124002] Fix session persistence in session.login command +- [144bb1cf] Add support for Datacenter.PowerOnMultiVM +- [d2ba47d6] vcsim: add simulator.Datastore type +- [937998a1] vcsim: set VirtualMachine summary.config.instanceUuid +- [1c76c63d] vcsim: update HostSystem.Summary.Host reference +- [d12b8f25] govc: object.collect support for raw filters +- [274f3d63] vcsim: add EventManager support +- [cc21a5ab] vcsim: stats related fixes +- [2d30cde3] Fix broken datastore link in VM +- [54b160b2] Several context changes: +- [f643f0ae] Leverage contexts in http uploads +- [fa2bee10] vcsim: avoid data races +- [29bd00ec] Remove omitempty tag from AffinitySet field +- [ca6f5d1d] vcsim: respect VirtualDeviceConfigSpec FileOperation +- [7811dfce] vcsim: avoid keeping the VM log file open +- [6cb9fef8] govc: fix host.info CPU usage +- [5786e7d2] govc: add -cluster flag to license.assign command +- [63c86f29] Add datastore.disk.cp command +- [828ce5ec] vcsim: add UpdateOptions support +- [a13ad164] Bump vcsa scripts to use 6.5U1 EP5 +- [c447244d] Add CloneSession support to govc and vcsim +- [d03f38fa] vcsim: add session support +- [44e8d85e] Added AttachScsiLun function ([#987](https://github.com/vmware/govmomi/issues/987)) +- [a3c9ed2b] vcsim: Add VM.MarkAsTemplate support +- [3f8349f3] Add cluster vm override commands ([#977](https://github.com/vmware/govmomi/issues/977)) +- [91fbd1f7] Add option to filter events by type ([#976](https://github.com/vmware/govmomi/issues/976)) +- [1d8b92d9] User server clock in session.ls ([#973](https://github.com/vmware/govmomi/issues/973)) +- [50735461] vcsim: more input spec honored in ReConfig VM +- [638d972b] vcsim: Initialize VM fields properly +- [2892ed50] Add '-rescan-vmfs' option to host.storage.info ([#966](https://github.com/vmware/govmomi/issues/966)) +- [d4ee331c] govc: allow columns in guest login password ([#972](https://github.com/vmware/govmomi/issues/972)) +- [e15ff586] Use IsFileNotFound helper in Datastore.Stat ([#969](https://github.com/vmware/govmomi/issues/969)) +- [aa0382c1] vcsim: Honor the input spec in ReConfig VM +- [465bd948] Hook AccountManager to UserDirectory +- [aef2d795] Destroy event history collectors ([#962](https://github.com/vmware/govmomi/issues/962)) +- [42f9a133] vcsim: Add HostLocalAccountManager +- [76f376a3] vcsim: workaround xml ns issue with pyvsphere ([#958](https://github.com/vmware/govmomi/issues/958)) +- [a1c49292] Ignore AcquireLocalTicket errors ([#955](https://github.com/vmware/govmomi/issues/955)) +- [bb150d50] Add missing dependency in gen script +- [0eacf959] toolbox: validate request offset in ListFiles ([#946](https://github.com/vmware/govmomi/issues/946)) +- [1d6aed22] Corrects datastore.disk usage which had not been generated ([#951](https://github.com/vmware/govmomi/issues/951)) +- [de717389] Corrects vm.info usage with required args ([#950](https://github.com/vmware/govmomi/issues/950)) +- [c5ea3fb2] Add datastore.disk inflate and shrink commands ([#943](https://github.com/vmware/govmomi/issues/943)) +- [adf4530b] Corrects host.shutdown ([#939](https://github.com/vmware/govmomi/issues/939)) +- [45c5269b] vcsim: add MakeDirectoryResponse ([#938](https://github.com/vmware/govmomi/issues/938)) +- [b4e77bd2] vcsim: copy RoleList for AuthorizationManager ([#932](https://github.com/vmware/govmomi/issues/932)) +- [426a675a] Fix [#933](https://github.com/vmware/govmomi/issues/933) ([#936](https://github.com/vmware/govmomi/issues/936)) +- [3be5f1d9] Add cluster.group and cluster.rule commands ([#928](https://github.com/vmware/govmomi/issues/928)) +- [2a8a5168] vcsim: apply vm spec NumCoresPerSocket ([#930](https://github.com/vmware/govmomi/issues/930)) +- [3a61d85f] vcsim: Configure dvs with the dvs config spec +- [3b25c720] CreateChildDisk 6.7 support ([#926](https://github.com/vmware/govmomi/issues/926)) +- [933ee3b2] Add VirtualDiskManager.CreateChildDisk ([#925](https://github.com/vmware/govmomi/issues/925)) +- [5f0f4004] vcsim: Add VirtualMachine guest ID validation ([#921](https://github.com/vmware/govmomi/issues/921)) +- [ef571547] vcsim: add QueryVirtualDiskUuid ([#920](https://github.com/vmware/govmomi/issues/920)) +- [0ea3b9bd] Implemened vm.upgrade operation. ([#918](https://github.com/vmware/govmomi/issues/918)) +- [27229ab7] vcsim: update ServiceContent to 6.5 ([#917](https://github.com/vmware/govmomi/issues/917)) +- [46c79c93] Add support for cpu + mem allocation to vm.change command ([#916](https://github.com/vmware/govmomi/issues/916)) + + +## [Release v0.16.0](https://github.com/vmware/govmomi/compare/v0.15.0...v0.16.0) + +> Release Date: 2017-11-08 + +### 💫 `govc` (CLI) + +- [0295f1b0] Fix VM clone when source doesn't have vNics +- [4fea6863] add tasks and task.cancel commands +- [ddd32366] add reboot option to host.shutdown + +### 💫 `vcsim` (Simulator) + +- [4543f4b6] preserve order in QueryIpPools ([#914](https://github.com/vmware/govmomi/issues/914)) +- [b385183e] return moref from Task.Run ([#913](https://github.com/vmware/govmomi/issues/913)) +- [e29ab54a] Implement IpPoolManager lifecycle +- [b227a258] add autostart option to power on VMs ([#906](https://github.com/vmware/govmomi/issues/906)) +- [ecde4a89] use soapenv namespace for Fault types +- [b1318195] various property additions +- [c19ec714] Generate similar ref value like VC +- [f3046058] Add moref to vm's summary +- [5f3fba94] validate authz privilege ids +- [c2caa6d7] AuthorizationManager additions +- [2cb741f2] Add IpPoolManager +- [a46ab163] VirtualDisk file backing datastore is optional +- [d347175f] add PerformanceManager +- [df3763d5] Implement add/update/remove roles +- [ed18165d] Generate device filename in CreateVM +- [e8741bf0] add AuthorizationManager +- [8961efc1] populate vm snapshot fields +- [add0245e] Add UpdateNetworkConfig to HostNetworkSystem +- [2aa746c6] Implement virtual machine snapshot +- [104ddfb7] set VirtualDisk backing datastore +- [505b5c65] Implement enter/exit maintenance mode +- [a1f8a328] Implement add/remove license +- [585cf5e1] add portgroup related operations +- [a7e79a7e] add fields support +- [895573a5] remove use of df program for datastore info +- [defe810c] add FileQuery support to datastore search +- [5fcca79e] add HostConfigInfo template +- [920a70c1] add HostSystem hardware property +- [0833484e] Fix merging of default devices +- [f6a734f5] Add cdrom and scsi controller to Model VMs + +### ⚠️ BREAKING + +### 📖 Commits + +- [7d879bac] Doc updates ([#915](https://github.com/vmware/govmomi/issues/915)) +- [4543f4b6] vcsim: preserve order in QueryIpPools ([#914](https://github.com/vmware/govmomi/issues/914)) +- [b385183e] vcsim: return moref from Task.Run ([#913](https://github.com/vmware/govmomi/issues/913)) +- [c8738903] Remove tls-handshake-timeout flag ([#911](https://github.com/vmware/govmomi/issues/911)) +- [e29ab54a] vcsim: Implement IpPoolManager lifecycle +- [3619c1d9] Use ProgressLogger for vm.clone command ([#909](https://github.com/vmware/govmomi/issues/909)) +- [13f2aba4] readme: fix formatting of listing ([#908](https://github.com/vmware/govmomi/issues/908)) +- [b227a258] vcsim: add autostart option to power on VMs ([#906](https://github.com/vmware/govmomi/issues/906)) +- [79934451] Add installation procedure in README.md ([#902](https://github.com/vmware/govmomi/issues/902)) +- [ecde4a89] vcsim: use soapenv namespace for Fault types +- [b1318195] vcsim: various property additions +- [4d8737c9] Switch to kr/pretty package for the -dump flag +- [e050b1b6] Couple of fixes for import.spec result +- [017138ca] import.spec not to assign deploymentOption +- [c19ec714] vcsim: Generate similar ref value like VC +- [0295f1b0] govc: Fix VM clone when source doesn't have vNics +- [f3046058] vcsim: Add moref to vm's summary +- [bfed5eea] [govc] Introduce TLSHandshakeTimeout parameter ([#890](https://github.com/vmware/govmomi/issues/890)) +- [1c1291ca] Support import ova/ovf by URL +- [3cb5cc96] Remove BaseResourceAllocationInfo +- [5f3fba94] vcsim: validate authz privilege ids +- [c91b9605] Add clone methods to session manager +- [c2caa6d7] vcsim: AuthorizationManager additions +- [2cb741f2] vcsim: Add IpPoolManager +- [644c1859] Updates to vm.clone link + snapshot flags +- [cf624f1a] Add linked clone and snapshot support to vm.clone +- [024c09fe] Fix govc events output +- [d4d94f44] govc/events: read -json flag and output events as json +- [24e71ea4] Fix vm.register command template flag +- [5209daf2] Fix object name suffix matching in Finder +- [a46ab163] vcsim: VirtualDisk file backing datastore is optional +- [d347175f] vcsim: add PerformanceManager +- [df3763d5] vcsim: Implement add/update/remove roles +- [8d5c1558] Support clearing vm boot order +- [ed18165d] vcsim: Generate device filename in CreateVM +- [df93050a] Fix CustomFieldsManager.FindKey method signature +- [e8741bf0] vcsim: add AuthorizationManager +- [8961efc1] vcsim: populate vm snapshot fields +- [17fb12a5] Add method to find a CustomFieldDef by Key +- [bc395ef0] vscim: Implement UserDirectory +- [add0245e] vcsim: Add UpdateNetworkConfig to HostNetworkSystem +- [2aa746c6] vcsim: Implement virtual machine snapshot +- [104ddfb7] vcsim: set VirtualDisk backing datastore +- [f3f51c58] Add support for VM export +- [505b5c65] vcsim: Implement enter/exit maintenance mode +- [a1f8a328] vcsim: Implement add/remove license +- [585cf5e1] vcsim: add portgroup related operations +- [a7e79a7e] vcsim: add fields support +- [e2944227] vim25: Move internal stuff to internal package +- [c4cab690] Add support for SOAP request operation ID header +- [895573a5] vcsim: remove use of df program for datastore info +- [4dd9a518] Skip version check when using 6.7-dev API +- [cc2ed7db] Change optional ResourceAllocationInfo fields to pointers +- [3f145230] Use base type for DVS backing info +- [df1c3132] Add vm.console command +- [829b3f99] Fixup recent tasks output +- [c4e473af] Add '-refresh' option to host.storage.info +- [3df440c8] toolbox: avoid race when closing channels on stop +- [badad9a1] toolbox: reset session when invalidated by the vmx +- [a1a96c8f] Include "Name" in device.info -json +- [defe810c] vcsim: add FileQuery support to datastore search +- [93f62ef7] Default vm.migrate pool to the host pool +- [5fcca79e] vcsim: add HostConfigInfo template +- [4fea6863] govc: add tasks and task.cancel commands +- [596e51a0] Use ovf to import vmdk +- [920a70c1] vcsim: add HostSystem hardware property +- [9e2f8a78] Add info about maintenance mode in host.info +- [78f3fc19] Avoid panic if ova import task is canceled +- [11827c7a] toolbox: default to tar format for directory archives +- [8811f9bf] toolbox: make gzip optional for directory archive transfer +- [9703fe19] toolbox: avoid blocking the RPC channel when transferring process IO +- [d6f60304] Add view and filter support to object.collect command +- [3527a5f8] Tolerate repeated Close for file follower +- [ddd32366] govc: add reboot option to host.shutdown +- [4d9061ac] toolbox: use host management IP for guest file transfer +- [7d956b6b] toolbox: add Client Upload and Download methods +- [c7111c63] toolbox: support single file download via archive handler +- [ebb77d7c] Use vcsim in bats tests +- [4bb89668] vCenter cluster testbed automation +- [ad960e95] toolbox: SendGuestInfo before the vmx asks us to +- [bdea7ff3] toolbox: update vmw-guestinfo +- [51d12609] toolbox: remove receiver from DefaultStartCommand +- [114329fc] Add host thumbprint for use with guest file transfer +- [5083a277] Add FindByUuid method for Virtual Machine +- [e1ab84af] toolbox: map exec.ErrNotFound to vix.FileNotFound +- [d1091087] toolbox: pass URL to ArchiveHandler Read/Write methods +- [cddc353c] toolbox: make directory archive read/write customizable +- [ba6720ce] toolbox: add http and exec round trippers +- [b35abbc8] Handle object names containing a '/' +- [ac4891fb] toolbox: fix ListFiles when given a symlink +- [60a6510f] Minor correction in README.md +- [0c583dbc] toolbox: support transferring /proc files from guest +- [0833484e] vcsim: Fix merging of default devices +- [c9aaa3fa] Move toolbox from vmware/vic to govmomi +- [f6a734f5] vcsim: Add cdrom and scsi controller to Model VMs +- [9d47dd13] Move vcsim from vmware/vic to govmomi + + +## [Release v0.15.0](https://github.com/vmware/govmomi/compare/v0.14.0...v0.15.0) + +> Release Date: 2017-06-19 + +### ⚠️ BREAKING + +### 📖 Commits + +- [b63044e5] Release 0.15.0 +- [3d357ef2] Add dvs.portgroup.info usage +- [72977afb] Add support for guest.FileManager directory download +- [94837bf7] Update examples +- [e1bbcf52] Update wsdl generator +- [b16a3d81] fix the WaitOptions struct, MaxWaitSeconds is optional, but we can set the value 0 +- [9ca7a2b5] Support removal of ExtraConfig entries +- [86cc210c] Guest command updates +- [9c5f63e9] Doc updates +- [6d714f9e] New examples: datastores, hosts and virtualmachines using view package +- [f48e1151] update spew to be inline with testify +- [6f5c037c] Adjust message slice passed to include +- [48509bc3] Fix package name +- [6f635b73] Add host.shutdown command +- [67b13b52] Add doc on metric.sample instance flag ([#726](https://github.com/vmware/govmomi/issues/726)) +- [8bff8355] Fix tail n=0 case ([#725](https://github.com/vmware/govmomi/issues/725)) +- [10e6ced9] Update copyright ([#723](https://github.com/vmware/govmomi/issues/723)) +- [6f8ebd89] Allow caller to supply custom tail behavior ([#722](https://github.com/vmware/govmomi/issues/722)) +- [35caa01b] Add options to host.autostart.add ([#719](https://github.com/vmware/govmomi/issues/719)) +- [2030458d] Add VC options command ([#717](https://github.com/vmware/govmomi/issues/717)) +- [0ccad10c] Exported FindSnapshot() Method ([#715](https://github.com/vmware/govmomi/issues/715)) +- [34202aca] Additional wrapper functions for SPBM +- [c7f718b1] Add AuthorizationManager {Enable,Disable}Methods +- [d5e08cd2] Add PBM client and wrapper methods +- [58019ca9] Add generated types and methods for PBM +- [58960380] Regenerate against current vmodl.db +- [f736458f] Support non-Go clients in xml decoder + + +## [Release v0.14.0](https://github.com/vmware/govmomi/compare/v0.13.0...v0.14.0) + +> Release Date: 2017-04-08 + +### ⚠️ BREAKING + +### 📖 Commits + +- [9bfdc5ce] Release 0.14.0 +- [3ba0eba5] Release 0.13.0 +- [86063832] Add object.find command +- [0391e8eb] Adds FindManagedObject method. +- [796e87c8] Include embedded fields in object.collect output +- [2536e792] Use Duration flag for vm.ip -wait flag +- [3aa64170] Merge commit 'b0b51b50f40da2752c35266b7535b5bbbc8659e3' into marema31/govc-vm-ip-wait +- [59466881] Implement EthernetCardBackingInfo for OpaqueNetwork +- [0d2e1b22] Finder: support changing object root in find mode +- [9ded9d10] Add Bash completion script +- [3bd4ab46] Add QueryVirtualDiskInfo +- [16f6aa4f] Emacs: add metric select +- [3763321e] Add unit conversion to metric CSV +- [b0b51b50] Add -wait option to govc vm.ip to allow non-blocking query +- [f0d4774a] Add json support to metric ls and sample commands +- [c9de0310] Add performance manager and govc metric commands +- [d758f694] Add check for nil envelope +- [ab595fb3] Remove deferred Close() call in follower's Read() + + +## [Release v0.13.0](https://github.com/vmware/govmomi/compare/v0.12.1...v0.13.0) + +> Release Date: 2017-03-02 + +### 💫 `vcsim` (Simulator) + +- [5f7efaf1] esxcli FirewallInfo fixes ([#661](https://github.com/vmware/govmomi/issues/661)) + +### ⚠️ BREAKING + +### 📖 Commits + +- [b4a3f7a1] Release 0.13.0 +- [5bf03cb4] Add vm.guest.tools command +- [b4ef3b73] Host is optional for MarkAsVirtualMachine ([#675](https://github.com/vmware/govmomi/issues/675)) +- [f4a3ffe5] Add vsan and disk commands / helpers ([#672](https://github.com/vmware/govmomi/issues/672)) +- [1f82c282] Handle the case where e.VirtualSystem is nil ([#671](https://github.com/vmware/govmomi/issues/671)) +- [dd346974] Remove object.ListView ([#669](https://github.com/vmware/govmomi/issues/669)) +- [4994038a] Wraps the ContainerView managed object. ([#667](https://github.com/vmware/govmomi/issues/667)) +- [93064c06] Handle nil TaskInfo in task.Wait callback [#2](https://github.com/vmware/govmomi/issues/2) ([#666](https://github.com/vmware/govmomi/issues/666)) +- [f1f5b6cb] Handle nil TaskInfo in task.Wait callback ([#665](https://github.com/vmware/govmomi/issues/665)) +- [f3cf126d] Support alternative './...' syntax for finder ([#664](https://github.com/vmware/govmomi/issues/664)) +- [9bda6c3e] Finder: support automatic Folder recursion ([#663](https://github.com/vmware/govmomi/issues/663)) +- [0a28e595] Add a command line option to change an existing disk attached to a VM ([#658](https://github.com/vmware/govmomi/issues/658)) +- [3e95cb11] Attach and list RDM/LUN ([#656](https://github.com/vmware/govmomi/issues/656)) +- [5f7efaf1] vcsim: esxcli FirewallInfo fixes ([#661](https://github.com/vmware/govmomi/issues/661)) +- [17e6545f] Add device option to WaitForNetIP ([#660](https://github.com/vmware/govmomi/issues/660)) +- [ba9e3f44] Fix vm.change test +- [e66c8344] Add the option to describe a VM using the annotation option in ConfigSpec ([#657](https://github.com/vmware/govmomi/issues/657)) +- [505fcf9c] Update doc +- [913c0eb4] Add support for reading and changing SyncTimeWithHost option ([#539](https://github.com/vmware/govmomi/issues/539)) +- [682494e1] Remove _Task suffix from vapp methods +- [733acc9e] Emacs: add govc-command-history +- [ea52d587] Add object.collect command ([#652](https://github.com/vmware/govmomi/issues/652)) +- [f49782a8] Update email address for contributor Bruce Downs + + +## [Release v0.12.1](https://github.com/vmware/govmomi/compare/v0.12.0...v0.12.1) + +> Release Date: 2016-12-19 + +### ⚠️ BREAKING + +### 📖 Commits + +- [6103db21] Release 0.12.1 +- [45a53517] Note 6.5 support +- [fec40b21] Add '-f' flag to logs command ([#643](https://github.com/vmware/govmomi/issues/643)) +- [40cf9f80] govc.el: auth-source integration ([#648](https://github.com/vmware/govmomi/issues/648)) +- [ca99f8de] Add govc-command customization option ([#645](https://github.com/vmware/govmomi/issues/645)) +- [ad6e5634] Avoid Finder panic when SetDatacenter is not called ([#640](https://github.com/vmware/govmomi/issues/640)) +- [b5c807e3] Add storage support to vm.migrate ([#641](https://github.com/vmware/govmomi/issues/641)) +- [1a7dc61e] govc/version: skip first char in git version mismatch error ([#642](https://github.com/vmware/govmomi/issues/642)) +- [6bc730e1] Add Slack links +- [e152c355] Add DatastorePath helper ([#638](https://github.com/vmware/govmomi/issues/638)) +- [5b4d5215] Add support for file backed serialport devices ([#637](https://github.com/vmware/govmomi/issues/637)) +- [f49bd564] Add vm.ip docs ([#636](https://github.com/vmware/govmomi/issues/636)) + + +## [Release v0.12.0](https://github.com/vmware/govmomi/compare/v0.11.4...v0.12.0) + +> Release Date: 2016-12-01 + +### ⚠️ BREAKING + +### 📖 Commits + +- [ab40ac73] Release 0.12.0 +- [e702e188] Disable use of service ticket for datastore HTTP access by default ([#635](https://github.com/vmware/govmomi/issues/635)) +- [1fba1af7] Attach context to HTTP requests for cancellations +- [79cb3d93] Support InjectOvfEnv without PowerOn when importing +- [117118a2] Support stdin as import options source +- [b10f20f4] Don't ignore version/manifest for existing sessions +- [82929d3f] Add basic VirtualNVMEController support +- [757a2d6d] re-generate vim25 using 6.5.0 + + +## [Release v0.11.4](https://github.com/vmware/govmomi/compare/v0.11.3...v0.11.4) + +> Release Date: 2016-11-15 + +### ⚠️ BREAKING + +### 📖 Commits + +- [b9bcc6f4] Release 0.11.4 +- [dbbf84e8] Add authz role helpers and commands +- [765b34dc] Add folder/pod examples +- [79cb52fd] Add host.account examples +- [2a2cab2a] Add host.portgroup.change examples + + +## [Release v0.11.3](https://github.com/vmware/govmomi/compare/v0.11.2...v0.11.3) + +> Release Date: 2016-11-08 + +### ⚠️ BREAKING + +### 📖 Commits + +- [e16673dd] Release 0.11.3 +- [629a573f] Add -product-version flag to dvs.create +- [83028634] Allow DatastoreFile follower to drain current body + + +## [Release v0.11.2](https://github.com/vmware/govmomi/compare/v0.11.1...v0.11.2) + +> Release Date: 2016-11-01 + +### ⚠️ BREAKING + +### 📖 Commits + +- [cd80b8e8] Release 0.11.2 +- [f15dcbdc] Avoid possible NPE in VirtualMachine.Device method +- [128b352e] Add support for OpaqueNetwork type +- [c5b9a266] Add host account manager support for 5.5 + + +## [Release v0.11.1](https://github.com/vmware/govmomi/compare/v0.11.0...v0.11.1) + +> Release Date: 2016-10-27 + +### ⚠️ BREAKING + +### 📖 Commits + +- [1a7df5e3] Release 0.11.1 +- [1ae858d1] Add support for VirtualApp in pool.change command +- [91b2ad48] Release script tweaks + + +## [Release v0.11.0](https://github.com/vmware/govmomi/compare/v0.10.0...v0.11.0) + +> Release Date: 2016-10-25 + +### ⚠️ BREAKING + +### 📖 Commits + +- [a16901d7] Release 0.11.0 +- [4fc9deb4] Add object destroy and rename commands +- [82634835] Add dvs.portgroup.change command + + +## [Release v0.10.0](https://github.com/vmware/govmomi/compare/v0.9.0...v0.10.0) + +> Release Date: 2016-10-20 + +### ⚠️ BREAKING + +### 📖 Commits + +- [bb498f73] Release 0.10.0 +- [468a15af] Release script updates +- [1c3499c4] Documentation updates +- [1e52d88a] Update contributors +- [e3d59fd9] Fix snapshot.tree on vm with no snapshots +- [711fdd9c] Add host.date info and change commands +- [16d7514a] Add govc session ls and rm commands +- [73c471a9] Add HostConfigManager field checks +- [d7f94557] Improve cluster/host add thumbprint support +- [fea8955b] Add session.Locale var to change default locale +- [eefe6cc1] Add service ticket thumbprint validation +- [3a0a61a6] Set default locale to en_US +- [aa1a9a84] TLS enhancements +- [9f0e9654] Treat DatastoreFile follower Close as "stop" +- [838b2efa] Support typeattr for enum string types +- [dcbc9d56] Make vm.ip esxcli test optional +- [9e20e0ae] Remove vca references +- [7c708b2e] Adding vSPC proxyURI to govc + + +## [Release v0.9.0](https://github.com/vmware/govmomi/compare/v0.8.0...v0.9.0) + +> Release Date: 2016-09-09 + +### ⚠️ BREAKING + +### 📖 Commits + +- [f9184c1d] Release 0.9.0 +- [e050cb6d] Add govc -h flag +- [a4343ea8] Set default ScsiCtlrUnitNumber +- [a920d73d] Add -R option to datastore.ls +- [f517decc] Fix SCSI device unit number selection +- [abaf7597] Add DatastoreFile helpers +- [7cfa7491] Make Datastore ServiceTicket optional +- [9ad57862] Add vm.migrate command +- [c66458f9] Add govc vm.{un}register commands +- [54c0c6e5] Checking result of reflect.TypeOf is not nil before continuing +- [ea0189ea] Fix flags.NewOptionalBool panic +- [a9cdf437] Add govc guest command tests +- [38dee111] Add VirtualMachine.Unregister func +- [98b50d49] make curl follow HTTP redirects +- [8a27691f] make goreportcard happy +- [bf66f750] Add govc vm snapshot commands +- [eb02131a] Validate vm.clone -vm flag value +- [62159d11] Add device.usb.add command +- [27e02431] Remove a bunch of context.TODO() calls. +- [a9cee43a] Fixing tailing for events command +- [4fa7b32a] Bump to 1.7 and start using new context pkg +- [4b7c59bf] Fix missing datastore name with vm.clone -force=false +- [e3642fce] Fix deletion of powered off vApp +- [63d60025] Support stdin/stdout in datastore upload/download +- [e149909e] Emacs: add govc-session-network +- [0ccc1788] Emacs: add govc json diff +- [f1d6e127] Add host.portgroup.change command +- [6f441a84] Add host.portgroup.info command +- [aaf40729] Add HostNetworkPolicy to host.vswitch.info +- [5ccb0572] Add json support to host.vswitch.info command +- [9d19d1f7] Support instance uuid in SearchFlag +- [2d3bfc9f] Add json support to esxcli command +- [bac04959] Support multiple NICs with vm.ip -esxcli +- [b3177d23] Add -unclaimed flag to host.storage.info command +- [b1234a90] govc - popualte 'Path' fiels in xxx.info output +- [7cab0ab6] Implemented additional ListView methods +- [498cb97d] Add 'Annotation' attribute to importx options. +- [223168f0] Add NetworkMapping section to importx options. +- [5c708f6b] Remove vendor target from the Makefile +- [f8199eb8] Handle errors in QueryVirtualDiskUUid function ([#548](https://github.com/vmware/govmomi/issues/548)) +- [73dcde2c] vendor github.com/davecgh/go-spew/spew +- [e1e407f7] vendor golang.org/x/net/context +- [e3c3cd0a] Populate network mapping from ovf envelope ([#546](https://github.com/vmware/govmomi/issues/546)) +- [fa6668dc] Add QueryVirtualDiskUuid function ([#545](https://github.com/vmware/govmomi/issues/545)) +- [17682d5b] Fixes panic in govc events + + +## [Release v0.8.0](https://github.com/vmware/govmomi/compare/v0.7.1...v0.8.0) + +> Release Date: 2016-06-30 + +### ⚠️ BREAKING + +### 📖 Commits + +- [c0c7ce63] Release 0.8.0 +- [ce4b0be6] Disable datastore service ticket hostname usage +- [3e44fe88] Add support for login via local ticket +- [acf37905] Add StoragePod support to govc folder.create +- [94d4e2c9] Include StoragePod in Finder.FolderList +- [473f3885] Avoid use of eval with govc env +- [4fb7ad2e] Add datacenter.create folder option +- [77ea6f88] Avoid vm.info panic against vcsim +- [95b2bc4d] Session persistence improvements +- [720bbd10] Add type attribute to soap.Fault Detail +- [ff7b5b0d] Add filtering for use of datastore service ticket +- [fe9d7b52] Add support for Finder lookup via moref +- [c26c7976] Use ticket HostName for Datastore http access +- [bea2a43c] Add govc/vm.markasvm command +- [9101528d] Add govc/vm.markastemplate command +- [982e64b8] Add vm.markastemplate + + +## [Release v0.7.1](https://github.com/vmware/govmomi/compare/v0.7.0...v0.7.1) + +> Release Date: 2016-06-03 + +### ⚠️ BREAKING + +### 📖 Commits + +- [2cad28d0] Fix Datastore upload/download against VC + + +## [Release v0.7.0](https://github.com/vmware/govmomi/compare/v0.6.2...v0.7.0) + +> Release Date: 2016-06-02 + +### ⚠️ BREAKING + +### 📖 Commits + +- [6906d301] Release 0.7.0 +- [558321df] Move InventoryPath field to object.Common +- [4147a6ae] Add -require flag to govc version command +- [d9fd9a4b] Add support for local type in datastore.create +- [650b5800] Fix vm.create disk scsi controller lookup +- [9463b5e5] Update changelog for govc to add datastore -namespace flag +- [4aab41b8] Update changelog with DatastoreNamespaceManager methods +- [4d6ea358] Support mkdir/rm of namespace on vsan +- [bb7e2fd7] InjectOvfEnv() should work with VSphere +- [91ca6bd5] Add host.service command +- [2f369a29] Add host.storage.mark command +- [b001e05b] Add -rescan option to host.storage.info command + + +## [Release v0.6.2](https://github.com/vmware/govmomi/compare/v0.6.1...v0.6.2) + +> Release Date: 2016-05-13 + +### ⚠️ BREAKING + +### 📖 Commits + +- [9051bd6b] Release 0.6.2 +- [3ab0d9b2] Get complete file details in Datastore.Stat +- [0c21607e] Convert types when possible +- [648d945a] Avoid xsi:type overwriting type attribute +- [4e0680c1] adding remove all snapshots to vm objects + + +## [Release v0.6.1](https://github.com/vmware/govmomi/compare/v0.6.0...v0.6.1) + +> Release Date: 2016-04-30 + +### ⚠️ BREAKING + +### 📖 Commits + +- [18154e51] Release 0.6.1 +- [47098806] Fix mo.Entity interface + + +## [Release v0.6.0](https://github.com/vmware/govmomi/compare/v0.5.0...v0.6.0) + +> Release Date: 2016-04-29 + +### ⚠️ BREAKING + +### 📖 Commits + +- [2c1d977a] Release 0.6.0 +- [cc686c51] Add folder.moveinto command +- [8e85a8d2] Add folder.{create,destroy,rename} methods +- [0ba22d24] Add Common.Rename method +- [61792ed3] Fix Finder.FolderList check +- [b6be92a1] Restore optional DatacenterFlag +- [53903a3a] Add OutputFlag support to govc about command +- [e66f7793] Add OptionManager and host.option commands +- [9d69fe4b] Add debug xmlformat script +- [f1786bec] Add option to use the same path for debug runs +- [99c8c5eb] Add folder.info command +- [eca4105a] Add datacenter.info command +- [71484c40] Add mo.Entity interface +- [388df2f1] Add helper to wait for multiple VM IPs +- [fc9f58d0] Add RevertToSnapshot +- [a4aca111] Add govc env command +- [ef17f4bd] Update CI config +- [fa91a600] Add host.account commands +- [44bb6d06] Update release install instructions +- [08ba4835] Leave AddressType empty in EthernetCardTypes +- [f9704e39] Add vm clone +- [e6969120] Add datastore.Download method +- [1aca660c] device.remove: add keep option + + +## [Release v0.5.0](https://github.com/vmware/govmomi/compare/v0.4.0...v0.5.0) + +> Release Date: 2016-03-30 + +### ⚠️ BREAKING + +### 📖 Commits + +- [c1b29993] Release 0.5.0 +- [b8549681] Use VirtualDeviceList for import.vmdk +- [cf96f70d] Remove debug flags from pool tests +- [f74a896d] Switch to int32 type for xsd int fields +- [074494df] Regenerate against 6.0u2 wsdl +- [ce9314c4] Include license header in generated files +- [957c8827] Add pointer field white list to generator +- [2c1d1950] Change pool recusive destroy to children destroy +- [5d34409f] Add dvs.portgroup.info command +- [216031c3] Update docs +- [f7dfcc98] Remove govc-test pools in teardown hook +- [556a9b17] Simplify pool destroy test +- [4e47b140] Add folder management to vm.create +- [7c33bcb3] Update test ESX IP in Drone secrets file +- [1b6ec477] Regenerate Drone secrets file +- [f64ea833] Implemented the ablitiy to tail the vSphere event stream - govc tail and force flag added to events command +- [fd7d320f] Including github.com/davecgh/go-spew/spew in go get +- [1d4efec0] Including github.com/davecgh/go-spew/spew in go get +- [424d3611] The -dump option now requests a recursive traversal as -json does +- [b45747f3] Added new -dump output flag for pretty printing underlying objects using davecgh/go-spew +- [a243716c] Run govc tests against ESX using Drone +- [fb75c63e] Double quotes network name to prevent space in name from failing the tests +- [564944ba] test_helper.bash updated to conditionally set env variables +- [c9c6e38f] Added new govc vm.disk.create -mode option for selecting one the VirtualDiskMode types +- [6922c88b] Add -net flag to device.info command +- [dff2c197] Fix VirtualDeviceList.CreateFloppy +- [c7d8cd3e] Ran gofmt on create.go +- [e077bcf5] Fix issue with optional UnitNumber (v2) +- [539ad504] Added arguments to govc vm.disk.create for thick provisioning and eager scrubbing, as requested in issue [#254](https://github.com/vmware/govmomi/issues/254) +- [e66c6df9] Handle import statement for types too +- [265d8bdb] Remove hardcoded urn:vim25 value from vim_wsdl.rb + + +## [Release v0.4.0](https://github.com/vmware/govmomi/compare/v0.3.0...v0.4.0) + +> Release Date: 2016-02-26 + +### ⚠️ BREAKING + +### 📖 Commits + +- [b3d202ab] Release 0.4.0 +- [749da321] Fix vm.change's ExtraConfig values being truncated at equal signs +- [13fbc59d] Add switch to specify protocol version in SOAPAction header +- [07013a97] Update CHANGELOG +- [bfe414fe] Allow vm.create to take datastore cluster argument +- [dda71761] Include reference to datastore in CreateDisk +- [855abdb3] Make NewKey function public +- [d0031106] Use custom datastore flags in vm.create +- [306b613d] Modify govc's vm.create to create VM in one shot +- [e96130b4] Add extra datastore arguments to vm.create +- [0a2da16d] Add datastore cluster methods to finder +- [c69e9bc1] Allow StoragePod type to be traversed +- [4d2ea3f4] added explicit path during clone +- [3d8eb102] Update missing property whitelist +- [779ae0a1] re-generate vim25 using 6.0 Update 1b (vimbase [#3024326](https://github.com/vmware/govmomi/issues/3024326)) +- [53c29f6a] Handle import statements same as include +- [a738f89d] Update govc.el URL +- [da2a249e] Doc updates +- [47e46425] govc.el: minor fixes for distribution as a package +- [8459ceb9] handle GOVC_TEST_URL=user:pass[@IP](https://github.com/IP) pattern +- [3b669760] Add Emacs interface to govc +- [7ec8028d] Update README to include Drone build status and local build instructions +- [2ec65fbe] Add config for Drone CI build +- [5437c466] introduce Datastore.Type() +- [983571af] introduce IsVC method and start using it +- [0732f137] Introduce AttachedClusterHosts +- [18945281] start using new helper functions for govc/flags +- [044d904a] Add some common functions to find/finder.go +- [534dabbd] Support vapp in pool.info command +- [4d9c6c72] Fix bats tests +- [5e04d5ca] Add -p and -a options to govc datastore.ls command +- [33963263] Added check for missing ovf deployment section + + +## [Release v0.3.0](https://github.com/vmware/govmomi/compare/v0.2.0...v0.3.0) + +> Release Date: 2016-01-15 + +### ⚠️ BREAKING + +### 📖 Commits + +- [501f6106] Mark 0.3.0 in change log +- [83a26512] Update contributors +- [995d970f] Print os.Args[0] in error messages +- [0a4c9782] Move stat function to object.Datastore +- [8a0d4217] Support VirtualApp in the lister +- [82734ef3] Support empty folder in SearchFlag.VirtualMachines +- [f64f878f] Add support for custom session keep alive handler +- [2d498658] Use OptionalBool for ExpandableReservation +- [ac9a39b0] Script to capture vpxd traffic on VCSA +- [3f473628] Script to capture and decrypt hostd SOAP traffic +- [eccc3e21] Move govc url.Parse wrapper to soap.ParseURL +- [e1031f44] Don't assume sshClient firewall rule is disabled +- [cd5d8baa] Let the lister recurse into a ComputeHost +- [b601a586] Specify the new entity's name upon import +- [a5e26981] Explicitly instantiate and register flags +- [aca77c67] Parameterize datastore in VM tests +- [37324472] Pass context to command and flag functions +- [6f955173] Minor optimization to encoding usage +- [0f4aee8b] Create VMFS datastore with datastore.create +- [ec724783] Add host storage commands +- [debdd854] Run license script +- [64022512] Fix license script to work for uncommitted files +- [5cb0c344] Remove host reference from HostFirewallSystem +- [4fb4052a] Change the comment that mentions ha-datacenter +- [b76ad0eb] Let the ESXi to figure out datastore name +- [918188dc] Add helper method to get VM power state +- [29a2f027] Add permissions.{ls,set,remove} commands +- [f27787a1] Add DatacenterFlag.ManagedObjects helper +- [0e629647] Option to disable API version check +- [42d899d0] Add commands to add and remove datastores +- [369e0e7f] Check host state in Datastore.AttachedHosts +- [7adf8375] Test that vm.info -r prints mo names +- [3198242e] Change ComputeResource.Hosts to return HostSystem +- [b34f346e] Support property collection for embedded types +- [8035c180] Fix vm nested hv option +- [b1d9d3c2] Update copyright years in code headers +- [c99e7bac] Add dvs commands +- [c30b7f17] Support DVS lookup in finder +- [094fbdfe] Embed Reference interface in NetworkReference +- [0657cf76] Add DVS helpers +- [6e96a1db] Add host.vnic.{service,info} commands +- [ae6b0b77] Add VsanSystem and VirtualNicManager wrappers +- [24297494] Add vsan flags to cluster.change command +- [4088502d] Add license.assigned.list id flag +- [d089489e] Add cluster.add license flag +- [31ee6e03] Add vm.change options to set hv/mmu +- [a414852e] Refactor host.add command to use HostConnectFlag +- [51543392] Add cluster.{create,change,add} commands +- [8262e1da] Add cluster related host commands +- [2443b364] Add HostConnectFlag +- [8ae7da82] Add object.HostSystem methods +- [0f630dd9] Add finder.Folder method +- [7cd5fbb5] Add bash function to save/load GOVC environments +- [12f26c21] Add object.Common.Destroy method +- [2ab8aa59] Add ComputeResource.Reconfigure method +- [5f47f155] Add flags.NewOptionalBool +- [25fe42b2] Add -feature flag to license list commands +- [2e6c0476] Add license.InfoList list wrapper +- [ef7371af] Add license assignment commands +- [5005e6e4] Add license.AssignmentManager +- [69a23bd4] Use object.Common in license.Manager +- [dbce3faf] Rename receiver variable for consistency +- [80705c11] Pass pointer to bps uint64 in last progress report +- [26e77c8e] VirtualMachine: Add Customize function on object.VirtualMachine +- [c2a78973] Add license.decode command +- [b3a7e07e] Add DistributedVirtualPortgroup support to vm.info +- [1b11ad02] Fix KeepAlive +- [3ecfd0db] Add HostFirewallSystem wrapper +- [9ded9c1a] KeepAlive support with certificate based login +- [cf2a879b] Add DiagnosticManager and logs commands +- [7b14760a] Update README.md +- [ad694500] Export Datastore.ServiceTicket method +- [76690239] Added a method to create snapshot of a virtual machine +- [6d4932af] Use service ticket for datastore file access +- [5fcc29f6] Fix vcsa ssh config +- [ac390ec8] Retry on empty result from property collector +- [f3041b2c] Add methods for client certificate based auth +- [b9edc663] Add extension manager and govc commands +- [9057659c] Fix key composition in building OVF spec +- [f56f6e80] Move OVF environment related code to env{,test}.go +- [b33c9aef] Add minimal doc to ovf package +- [3d40aefb] Added verbose option to the import.spec feature +- [1df0a81d] change for looking up a VM using instanceUUID +- [5f4d36cd] Introduce govc vapp.{info|destroy|power} +- [88795252] Handle the import.spec case where no spec file is provided +- [bcdc53fb] Add inventory path to govc info commands +- [305371a8] Collect govc host and pool info in one call +- [bfd47026] Relax the convention around importing an ova +- [3742a8aa] don't start goroutine while context is nil + + +## [Release v0.2.0](https://github.com/vmware/govmomi/compare/v0.1.0...v0.2.0) + +> Release Date: 2015-09-15 + +### ⏮ Reverts + +- [2900f2ff] Add Host information to vm.info +- [8bec13f7] Fix git dirty status error in build script + +### ⚠️ BREAKING + +### 📖 Commits + +- [b3315079] Mark 0.2.0 in change log +- [cc3bcbee] Add mode argument to release script +- [ae4a6e53] Build govc with new cross compilation facilities +- [4708d165] Derive CONTRIBUTORS from commit history +- [00909f48] Move contrib/ -> scripts/ +- [a0f4f799] Capitalization +- [13baa0e4] Split import functionality into independent flags +- [6363d0e2] Added ovf.Property output to import.spec +- [7af121df] Update change log +- [f9deb385] Fix event.Manager category cache +- [7f0a892d] Avoid tabwriter in events command +- [29601b46] Use vm.power force flag for hard shutdown/reboot +- [ea833cf5] Add VirtualDiskManager CreateVirtualDisk wrapper +- [bfabd01d] Interative clean up of bats testing +- [7cba62d9] Clean up of vcsa creation script +- [631d6228] Add serial port URI info to device.info output +- [0b31dcff] Add -json support to device.info command +- [54e324d1] Add govc vm.info resources option +- [9cc5d8f5] Add helper method to wait for virtual machine power state. +- [9ddd6337] Remove superfluous math.Pow calculations +- [5272b1e9] Added common method of humanizing byte strings +- [3145d146] Add helper method to check if VMware Tools is running in the guest OS. +- [e4f4c737] Misc clean up +- [01f2aed0] Add host name to vm.info +- [f24ec75a] Use property.Collector.Retrieve() in vm.info +- [a779c3b7] Renamed vm.info VmInfos back to VirtualMachines +- [2900f2ff] Revert "Add Host information to vm.info" +- [2a567478] Add -hints option to host.esxcli command +- [1f0708e2] Add options to importing an ovf or and ova file +- [debde780] Only retrieve "currentSession" property +- [b5187c16] Update CONTRIBUTORS +- [3e4ced8c] Added the ability to specify ovf properties during deployment +- [688a6b18] Introduce more VirtualApp methods +- [b1f0cb0c] Add flag to specify destination folder for import.ovf and import.ova +- [c9fcf1ce] Add check for error reading ova file +- [edb0a2cf] clone vmware/rbvmomi repo if it's missing +- [40c26fc6] use e.Object.Reference().Type as suggested by Doug +- [c1442f95] introduce CreateVApp and CreateChildVM_Task +- [25405362] add VirtualAppList and VirtualApp methods to Finder +- [121f075c] Add CustomFieldsManager wrapper and cli commands +- [dd016de3] include VirtualApp in ls -l output +- [b5db4d6d] Provide ability to override url username and password +- [11d5ae9c] Add OVF unmarshalling +- [135569e7] Update travis.yml for new infra +- [822432eb] Make govet stop complaining +- [baf9149e] Add datastore.info cli command +- [2b93c199] Add serial port matcher to SelectByBackingInfo +- [26ba22de] Merge branch 'gavrie-master' +- [62591576] Add Host information to vm.info +- [a90019ab] Add methods for useful properties to VirtualMachine +- [502963c4] Add Relocate method to VirtualMachine +- [7f4b6d38] Add String method to objects for pretty printing +- [99f57f16] Add events helpers and cli command +- [4c989ac3] Update CONTRIBUTORS +- [ad7d1917] Update to vim25/6.0 API +- [ad39adb9] Add net.address flag +- [e01555f9] Add command to add host to datacenter +- [efbd3293] Stop returning children from `ManagedObjectList` +- [d16670f5] Update CONTRIBUTORS +- [97fbf898] Mention GOVC_USERNAME and GOVC_PASSWORD in CHANGELOG +- [8766bda0] Add test to check for flag name collisions +- [791b3365] Remove flags for overriding username and password +- [85957949] include GOVC_USERNAME and GOVC_PASSWORD in govc README +- [8584259a] Export variables in release script +- [14889008] Add test for GOVC_USERNAME and GOVC_PASSWORD +- [c0a984cd] Only run license tests against evaluation license +- [293ac813] Allow override of username and password +- [e053bdf2] Add extraConfig option to vm.change and vm.info +- [1dec0695] Update CONTRIBUTORS +- [1acf418c] Add Usage for host.esxcli +- [2e00fdb1] Modify archive.go bug +- [985291d5] Add missing types to list.ToElement +- [871f5d4f] Add script to create a draft prerelease +- [8bec13f7] Revert "Fix git dirty status error in build script" +- [c825a3c7] Only use annotated tags to describe a version +- [66320cb0] Retry twice on temporary network errors in govc +- [67be5f1d] Add retry functionality to vim25 package +- [fba0548b] Add method to destroy a compute resource +- [2add2f7a] Add methods to add standalone or clustered hosts +- [de297fcb] Add ability to create, read and modify clusters +- [f10480af] Change finder functions to no longer take varargs +- [4bc93a66] Fix resource pool creation/modification +- [b434a9a8] Rename persist flag to persist-session +- [d85ad215] Ignore ManagedObjectNotFound in list results +- [4c497373] Add example that lists datastores +- [5d153787] Update govc CHANGELOG +- [0165e2de] Add flag to toggle persisting session to disk +- [8acb2f28] Add Mevan to CONTRIBUTORS +- [add15217] Ignore missing environmentBrowser field +- [447d18cd] Fix error when using SDRS datastores +- [e85f6d59] Find ComputeResource objects with find package +- [55f984e8] Test package only depends on vim25 +- [dbe47230] Drop omitempty tag from optional pointer fields +- [749f0bfa] Interpret negative values for unsigned fields +- [49a34992] Update CHANGELOG +- [263780f3] Update code to work with bool pointer fields +- [93aad8da] Make optional bool fields pointers +- [b7c51f61] Return errors for unexpected HTTP statuses +- [62ca329a] Abort client tests on errors +- [ae345e7f] Rename LICENSE file +- [a783a8c6] Add govc CHANGELOG +- [ba707586] Add commands to configure the autostart manager +- [af6a188e] Re-enable search index test +- [ceea450c] Update govc README +- [ea5c9a52] Fix git dirty status error in build script + + +## v0.1.0 + +> Release Date: 2015-03-17 + +### ⚠️ BREAKING + +### 📖 Commits + +- [477dcaf9] Cross-compile govc using gox +- [8593d9c7] Add version variable that can be set by the linker +- [fb38ca45] Add CHANGELOG +- [76f8f1a1] Add package docs to client.go +- [27bf35df] Use context.Context in client in root package +- [f3b8162f] Comment out broken test +- [a1d9d1e7] Drop the _gen filename suffix +- [91650a1f] Add context.Context argument to object package +- [1814113a] Use vim25.Client throughout codebase +- [b977114e] Move property retrieval functions to property package +- [8c3243d8] Add lightweight client structure to vim25 package +- [ec4b5b85] Add context.Context argument to find/list packages +- [7eecfbc7] Make Wait function in property package standalone +- [6c1982c8] Add keep alive for soap.RoundTripper +- [1324d1f0] Return nil UserSession when not authenticated +- [ae7ea3dd] Comments for task.Wait +- [a53a6b2c] Add context parameter to object.Task functions +- [f6f44097] Move functionality to wait for task to new package +- [ad2303cf] Move Ancestors function to vim25/mo +- [fb9e1439] Move PropertyCollector to new property package +- [a6618591] Move Reference to vim25/mo +- [bfdb90f1] Bind virtual machine to guest operation wrappers +- [ec0c16a7] Move HasFault to vim25/types +- [683ca537] Move wrappers for managed objects to object package +- [223a07f8] Add GetServiceContent function to vim25/soap +- [25b07674] Decouple factory functions from client +- [b96cf609] Move SessionManager to new session package +- [ea8d5d11] Return on error in SessionManager +- [7d58a49e] Mutate copy of parameter instead of parameter itself +- [e158fd95] Marshal soap.Client instead of govmomi.Client +- [1336ad45] Embed soap.Client in govmomi.Client +- [15cfd514] Work with pointer to url.URL +- [be2936f8] Move guest related wrappers to new guest package +- [b772ba28] Move LicenseManager to new license package +- [7ac1477f] Move EventManager to new event package +- [2053e065] Retrieve dependencies before running test +- [2d14321e] Add context.Context argument to RoundTripper +- [64f716b2] Include type of request in summarized debug log +- [40249c87] Store reference to http.Transport +- [ac77f0c5] Move debugging code in soap.Client to own struct +- [c8fab31b] Loosen .ovf match in ova.import +- [9f685e92] And further fixing the merge... go fmt. +- [8dbb438b] Merge remote-tracking branch 'upstream/master' into event_manager +- [e57a557c] created session manager wrapper +- [5525d5c6] Change return pattern in CreateDatacenter +- [8acd5512] Update contributors +- [7138d375] Coding style consistency +- [951e9194] added SessionIsActive to Client +- [2211e73d] Add CreateFolder method +- [eef40cc0] Add Login/Logout functions to client struct +- [3c7dea04] Update contributors +- [9c4a9202] Fixed error when attempting to access datastore +- [05ee0e62] Add PropertiesN function on client struct +- [01ee2fd5] Adding EventManager so that events can be queried for +- [8d10cfc7] Restrict permissions on session file +- [88b5d03c] Key session file off of entire URL +- [9354d314] Error types for getter functions on finder +- [a30287dc] Add description for pool.create +- [77466af0] Prefix option list in help output +- [cbb8d0b2] Create multiple resource pools through pool.create +- [8d4699d8] Add usage and description for pool.destroy +- [2e195a92] Change pool.change to take multiple arguments +- [38e4a2b2] Add usage and description for pool.info +- [2f286768] Add usage and description for pool.create +- [413fa901] Set insert_key = false +- [d6c2b33e] Update travis.yml +- [b878c20a] Adding CustomizationSpecManager +- [7c8f3e56] Add vm mark as vm and mark as template features +- [033d02e9] Update contributors +- [18919172] Add cpu and memory usage to host.info +- [b29f93c1] Adding the RegisterVM task. +- [e6bf8bb5] Add error types for Finder +- [852578b9] Support multiple hosts in host.info command +- [f1899c63] Set InventoryPath field +- [3a5c1cf3] Add InventoryPath field +- [624f21a4] Add resource pool cli commands +- [4c7cd61f] Add ResourcePool wrapper methods +- [761d43e5] Include ResourcePool in ls -l output +- [d2daf706] Support nested resource pools in lister +- [4d9d9a72] Add vm.change cli command +- [e6ebcd7f] bats fixup: destroy datacenter +- [65838131] Disable vcsa box password expiration +- [7a6e737b] Add CONTRIBUTORS file +- [1cbe968d] Issue [#192](https://github.com/vmware/govmomi/issues/192): HostSystem doesn't seem to be returning the correct host. +- [116a4044] fix a problem of ignored https_proxy environment variable with https scheme +- [df423c32] Add create and destroy datacenter to govc. +- [035bd12c] Usage for devices.{cdrom,floppy}.* +- [68e50dd3] make storage resource manager +- [b28d6f42] Specify default network in test helper +- [4b388e67] Fix boot order test +- [4414a07e] Expand vm.vnc command +- [e329e6e7] rename the session file for windows naming check +- [706520fa] use filepath for filesystem related path operations +- [ceb35f13] Add -f flag to datastore.rm +- [6498890f] Default VM memory to 1GiB +- [591b74f4] Include description for device.cdrom commands +- [815f0286] Add usage to device.cdrom.insert +- [f2209c2b] Flag description casing +- [5e52668c] Add usage to import commands +- [23cf4d35] Expand datastore.ls +- [bca8ef73] Expose underlying VimFault through Fault() function +- [90edb2bc] Add Usage() function to subset of commands +- [afdc145a] Implement subset of license manager +- [14765d07] Add net.adapter option to network flag +- [18c2cce0] Add CreateEthernetCard method +- [9b2730f0] Don't run vm.destroy if there is no input +- [611ced85] Add new ops to vm.power command +- [6cd9f466] Add VM power ops +- [7918063c] Work on README +- [db17cddd] Check minimum API version from client flag +- [df075430] Don't run datastore.rm if there is no input +- [e49a6d57] Move environment variables names into constants +- [2cfe267f] Add device.scsi command +- [6df44c1a] Support scsi disk.controller type in vm.create +- [39a60bbf] Add CreateSCSIController method +- [136fabe5] Rename vm.create disk.adapter to disk.controller +- [9c51314c] Change disk related commands to use new helpers +- [b0c895e5] Add VirtualDisk support to device helpers +- [a00f4545] Add helpers for creating disks +- [16283936] Add FindDiskController helper +- [dda056dc] Add VirtualDeviceList.FindSCSIController method +- [5402017a] FindByBackingInfo -> SelectByBackingInfo +- [0ff5759c] Add vm disk related bats tests +- [8f1e183a] Output disk file backing in device.info +- [e7cfba4b] Remove datastore test files +- [6b883be5] Use DeviceAdd helper in vm.network.add command +- [eb5881ae] Use device name in vm.network.change command +- [b7503468] Remove vm.network.remove command +- [0b81619a] Add vm.network.change cli command +- [0af5c4cf] Use VirtualDeviceList helpers in vm.network.remove +- [94c62da0] Add VirtualDeviceList FindByBackingInfo method +- [c247b80c] Move govc resource finders to govmomi/find package +- [5f0c8dd4] Add vm.info bats test +- [5d99454d] mv govc/flags/list -> govmomi/list +- [028bd3ff] Fix HostSystem.ResourcePool with cluster parent +- [48e25166] Add ls bats test +- [c5f24bce] Add host bats test +- [f965c9ad] Add default GOVC_HOST to vcsim_env +- [77fc8ade] Add network flag required test +- [b1236bf8] Add wrapper to manually run govc against vcsim +- [68831a1f] Fix network device.remove test +- [4649bf1f] Default vcsim box to 4G memory +- [b3f71333] Simplify vcsim_env helper +- [2ca11cde] Answer pending VM questions from govc +- [b6c3ff31] Move govc/test Vagrant boxes +- [b1b5b26e] Change network flag to use NetworkReference +- [83f49af7] Add network bats test +- [a8ffa576] Add NetworkReference interface +- [6fe62e29] Add vcsim_env helper +- [a616817d] Fix collapse_ws helper +- [0614961e] Add DistributedVirtualPortgroup constructor +- [1ddf6801] Cache esxcli command info +- [c713b974] Add table formatter to esxcli command +- [fd19a011] Include esxcli method info in response +- [3c9a436f] Explicit exit status check in assert_failure +- [5a63bc06] Collapse whitespace in assert_line helper +- [c9bd4312] Change vm.ip -esxcli to wait for ip +- [e97e5604] boot order test fixups +- [0e128e0d] 32M is plenty of memory for ttylinux +- [85ded933] Add test cleanup script +- [2bc707e7] Add device.serial cli commands +- [17fb283a] Add serial port device related helpers +- [d9b846d1] Add device.boot tests +- [b5a21e4e] Add device.floppy cli commands +- [d1d39fc3] Add floppy device related helpers +- [1e2c54c0] Refactor disk logic into disk.go +- [9dff8e74] Fix attach disk error checks +- [0f352ec3] Add vm.disk.attach +- [bdd7b37b] Refactor vm.disk.add to vm.disk.create +- [ae2e990e] Add govc functional tests +- [a707fae6] Fix alignment for 32-bit go +- [13274292] Default cli client url.User field +- [17df67ad] Add device.boot cli command +- [3c345ad7] Add device.ls -boot option +- [3b25234c] Add boot order related VirtualDeviceList helpers +- [f996c7d0] Add VirtualMachine BootOptions wrappers +- [4f3b935b] Add some DeviceType constants +- [86f90c52] Add VirtualDeviceList.Type method +- [5f3b95d7] Output MAC Address in device.info +- [58c3c64e] Add VirtualMachineList.PrimaryMacAddress helper +- [67fea291] Fix import.ovf with relative ovf source path +- [22602029] Support non-disk files in import.ovf +- [92175548] Add Upload.Headers field +- [f095536d] Fix import.ova command +- [5093303a] Add device related govc commands +- [18644254] Add device list related helpers +- [6803033e] Add device list helpers +- [4f8cd87c] Switch to BaseOptionValue for vm extra config +- [76662657] Regenerate types +- [46ec389f] Generate interface types for all base types +- [f78df469] Remove Client param from ResourcePool methods +- [ca3cd417] Add Client reference to ResourcePool +- [ffc306cc] Add Client reference to Network +- [c1138fc4] Remove Client param from HttpNfcLease methods +- [6f983a49] Add Client reference to HttpNfcLease +- [d2d566d0] Remove Client param from HostSystem methods +- [60bf1770] Add Client reference to HostSystem +- [e32542c1] Remove Client param from HostDatastoreBrowser methods +- [8956959a] Add Client reference to HostDatastoreBrowser +- [79e7da1d] Remove Client param from Folder methods +- [68b3e6dc] Add Client reference to Folder +- [da5b8ec0] Remove Client param from Datastore methods +- [f89dd25a] Add Client reference to Datastore +- [1b372efa] Remove Client param from Datacenter methods +- [ce320403] Add Client reference to Datacenter +- [b99a9529] Remove Client param from VirtualMachine methods +- [eb700d65] Add Client reference to VirtualMachine +- [673485e4] Remove config check from esxcli.GuestInfo.IpAddress +- [667df16a] Add VCSA Vagrant box +- [66b7daab] Use single consistent pattern to populate FlagSet +- [8fa06b5a] Export NewReference function +- [a4e11a3a] Check if info is nil before using it +- [8bbe7361] Add ManagedObject wrappers +- [9d5df71d] Add vm.ip -esxcli option +- [1818a2a6] Add esxcli helper for guest related info +- [ac6efdc9] Use vim.CLIInfo for esxcli command flags and help +- [5b9b34bc] Remove Cdrom function from disk flag +- [01d201ee] Use new esxcli command parser +- [7531d60e] New esxcli command parser +- [a27c9bd5] Refactor esxcli to esxcli.Executor +- [fdb2d2d0] Refactor unmarshal +- [2dd9910d] Add esxcli related types and methods +- [aad819e8] Add IsoFlag +- [df11fc04] Handle empty values in esxcli +- [6ceff6a4] Fix default network in NetworkFlag +- [bc39649d] Add DistributedVirtualPortgroup wrapper +- [a7eb1d1e] Add DVS support to NetworkFlag +- [71898a73] Support DistributedVirtualPortgroup in lister +- [1cf31f03] Regenerate mo types +- [1e7c1957] Generate mo types regardless of props +- [549a2712] tasks are no longer generated +- [fcf2cd94] Remove unused DiskFlag.Copy method +- [e494c312] Add DiskFlag adpater option +- [71e5eea2] Add host.esxcli command +- [5d0fe65c] Replace panic by error in host system flag +- [a2a7c8ff] Remove newOvf() +- [d8e94d8f] Use default host system where possible +- [67835263] Move HostNetworkSystem getter to HostSystemFlag +- [348258b5] Move resource pool getter to host system object +- [03f94f4b] Default URL scheme and path if not specified +- [73b11f40] Move progress reader to vim25/progress +- [34f73f0a] Refactored progress reporting infrastructure +- [79f15899] Include environment variable names in help +- [1de37e80] Don't skip certificate verification by default +- [4a533b21] Support ClusterComputeResource in list flag +- [817df9d1] Include remote path in importable +- [a0944d82] Import vm.network commands +- [2fd2f026] Add vm.network.remove command +- [e3307b6f] Add vm.network.add command +- [2ac39a1e] Import host.portgroup commands +- [27686532] Add host.portgroup.remove command +- [46545dd9] Add host.portgroup.add command +- [29d8ed38] Add host.vswitch.remove command +- [c2bfbccf] Add host.vswitch.info command +- [f05e3e0a] Include host/vswitch commands +- [17094882] Add host.vswitch.add cli command +- [febf70cb] Add SearchFlag HostNetworkSystem helper +- [cb41663b] Add HostSystem ConfigManager getter +- [6f482eb1] Add HostConfigManager wrapper +- [851cb8d3] Add HostNetworkSystem wrapper +- [8bb8b613] Implement flag.Value interface in NetworkFlag +- [41ebd843] Change destination path for import.vmdk command +- [a6e0f1d4] Don't create VM if vmx already exists +- [b48f0080] Check that DiskFlag.Disk exists +- [8fcafba3] Use DatastoreFlag.Stat method in vmdk.PrepareDestination +- [29daec38] Add DatastoreFlag Stat method +- [29ca9c4a] Use aggregate progess in lease updater +- [de422b52] Enable debug logging with environment variable +- [48690f77] Add script that summarizes debug trace information +- [c515f6e1] Add guest.rm cli command +- [ade53d1e] Remove recursive arg from DeleteFileInGuest +- [63ec87fd] Add guest.start cli command +- [a5dccc14] Add guest.kill cli command +- [8e1abdd4] Add guest.mktemp cli command +- [8d287c3d] Add guest.ls cli command +- [79a67b2d] Fix a few tabwriter outputs Stderr -> Stdout +- [6dc9803f] Remove TODO +- [48a55bbd] Add guest.ps cli command +- [bed7c508] vm arg is required for guest ops +- [fc387eb6] Add example/project links +- [6e75fbf6] Add example: Create and configure a vCenter VM +- [068cc973] Add vm.disk.add command +- [ae42925a] ImportVApp host argument is optional +- [a959e782] Use OutputFlag.Log for ovf warnings +- [db30f1d4] Stream uploads directly from the .ova file +- [b0809106] Add import.Archive interface +- [1faa4e8b] Add Client.Upload method +- [47fe7028] Split datastore.import into multiple commands +- [66a468e2] Rename datastore.delete -> datastore.rm +- [3afcdf5d] Register commands with explicit name +- [07a12472] Load fewer properties where possible +- [3f2d9e5e] Cache rich type info for managed objects +- [be3b5ab1] Install go vet for travis +- [bcf792a0] Add go vet to travis script +- [6be65b35] Rename OutputWrite.WriteTo method to Write +- [b2c603f2] go vet: format related warnings +- [7403b749] go vet: composite literal uses unkeyed fields +- [98ac1aaf] Add NewFolder func +- [eea431c8] Change NewDatastore signature +- [7dbc2b25] Add NewResourcePool func +- [8467fbfd] Support importing VMDKs into ESXi machines +- [8a501f08] Be specific about channel direction +- [abeb8e83] Add DeleteVirtualDisk function +- [11d67d27] Add datastore.import support for .ova files +- [c29ff5c0] Improve about command output +- [bdeb77fd] Add progress for ovf datastore.import +- [4810135c] Ignore PowerOff error in vm.destroy command +- [48c2bbd3] Stop Ticker in ProgressLogger +- [8dfa7db3] Include Client.URL's port in ParseURL +- [c2330cf6] Add progress aggregator for govc +- [d7274985] Use virtual machine flag for vnc command +- [85649cd8] Remove vim25/tasks pkg +- [8f1a2803] Return task objects for every task function +- [df9af568] Add test for progress reader +- [1ddaf841] progessReader passthrough is progress channel is nil +- [9544be13] Add travis ci config +- [bad48a77] Use time.Equal when comparing time.Time +- [e4aeadc2] Upload progress for datastore.import +- [295b4597] Move computation of progress percentage and detail +- [c72543ac] Remove trailing _ from command name +- [2d96f8a5] Add progress report to datastore.{upload,download} +- [ae8509c1] Add functions to about command +- [583a4aca] Merge branch 'readme' +- [2b03454b] Add ovf support to datastore.import +- [fcdfafd6] Add options param to Client.UploadFile +- [0f218092] Move ParseURL helper to Client +- [9f9996e2] Published -> available +- [378e32b9] Fix +- [dae1e4e5] Use WaitForProperties in VirtualMachine.WaitForIP +- [a0335bac] Initial govc readme +- [65050902] Initial govmomi readme +- [231996ff] Add custom HttpNfcLease helpers +- [3293be25] Add Client.WaitForProperties method +- [a28b4fc0] Add generated HttpNfcLease wrapper +- [b610aa5c] Add ResourcePool.ImportVApp wrapper +- [6f9f316f] Add OvfManager getter +- [4ab1b230] Add generated OvfManager wrapper +- [a3e28532] Use virtual machine flag for guest ops +- [8044501f] Configure parent disk on create +- [1786687d] Generate mapping for interface type names +- [f3fa15c1] Use interface type name if type attr is missing +- [27cda4d6] Ignore EEXIST on mkdir in guest +- [c4517301] Use search flag from host system flag +- [9f9b0c9d] Initialize SearchFlag from Register hook +- [02108dd4] Call user function before recursing (govc/cli) +- [73b14a66] Don't overwrite fields (govc/cli) +- [0a5da729] Prefix search flags with entity name +- [cc6aa166] Isset -> IsSet +- [af8adde5] Consistently name pointer receiver 'flag' +- [5cd9a61e] Rename environment variables GOVMOMI -> GOVC +- [45eca426] Use list flag to find host system +- [15fe3728] Use list flag to find resource pool +- [1938ff93] List resource pool in compute resource +- [051ba306] Use list flag to find network +- [4015bec1] Create a VM with a read only parent disk +- [9e98ef07] Upload disk to import to directory +- [72fa245c] Split import into upload and import steps +- [d46b4e51] Add datastore.import command +- [2ba133de] Move datastore path helper to datastore struct +- [ba92fed2] Capture request and response bodies in debug mode +- [2660649a] Add datastore.ls cli command +- [2c8b9fd5] Add Datastore.Browser method +- [8e6805f5] Add HostDatastoreBrowser wrapper +- [6aef2e27] Change generated Base interfaces to a Get method +- [cb0c5763] Add datastore.cp cli command +- [d7cc920a] Add datastore.mv cli command +- [3601ab3b] Add Copy, Move FileManager methods +- [8c62e27e] Datastore commands take paths as regular arguments +- [a740c827] Use list flag to find datastore +- [b7d4b208] Add guest.getenv command +- [e72b79f9] Add guest.chmod command +- [5bd30d15] Use FileAttr flag in guest.upload +- [8c889f03] Add guest FileAttr flag +- [22f854ef] Fix guest RewriteURL method +- [69af5618] Retrieve object ancestors if listing a relative path +- [882faef4] Import vm/guest commands +- [a8fdd5ab] Add guest.upload command +- [93815beb] Add guest.download command +- [108f118d] Add guest.rmdir command +- [77c1f59d] Add guest.mkdir command +- [98283e1a] Common flags and helpers for guest command +- [37065ae1] Add cli flag for guest authentication +- [fc5eb7a7] More GuestFileManager wrappers +- [8611b851] Rename cli datastore upload/download receivers +- [2a058397] Move {Upload,Download}File methods to soap.Client +- [75dfb253] Use list flag to find datacenter +- [b0557434] Add GuestOperationManager wrapper +- [9fb9b66e] Load datacenter name for datastore URL +- [011790a6] Fix DatastoreFlag lookup +- [b7c12086] Add vm.ip command +- [17b0879d] Report progress from vm.power command +- [0a10a798] Avoid panic if ClientFlag url is not set +- [33c26af2] Long/short output for ls command +- [0c97323b] Make traversal of leaf nodes in list code configurable +- [ad0e3778] Add soap.Client.URL method +- [f3289833] Destroy multiple VMs +- [90d80fb3] Power on/off multiple VMs +- [97c2034b] Rename c -> cmd, client -> c +- [8ea428a4] Initialize vm commands with search type +- [1e175eab] Change xml.Decoder.AddType to TypeFunc +- [754da687] Change xml.Decoder.AddType to TypeFunc +- [8cbebfcb] Use list flag from search flag +- [43950349] Use list flag from vm.info cli command +- [0c3080c0] List relative to configurable object +- [c8438410] Extract list functionality as flag +- [ad7bac7a] Support vm.create with -disk .iso +- [189a2231] Add Isset function to search flag +- [bd38dd9b] Add vm.destroy cli command +- [24da8d1c] Add VirtualMachine.Destroy method +- [79466361] Include client counter in debug file prefix +- [11ac68f1] Check if session is valid before returning it +- [685f9554] Return fault from missing set if applicable +- [44575370] Method fault is a base class +- [f1258736] Optionally power on vm after creation +- [dd38436e] Function to map strings to types +- [9a0dde0a] Return VirtualMachine from CreateVM +- [29c8d2ee] Return result from Client.waitForTask +- [a368944d] Move error wrapper to soap package +- [bb62b6a6] Fix client_test compile +- [e0ce3a86] DatastoreFlag refactoring +- [4cd1e77f] Check for DatastorePath required flag +- [79887bf3] Rename DatastorePath to DatastorePathFlag +- [03f2520e] Persist session to disk +- [3a9169e2] Unembed soap.Client from govmomi.Client +- [b510dc18] Implement vm.create cli command +- [06d2e159] Add cli Disk flag +- [b0ce5181] Add cli Network flag +- [8736db1c] Add cli VmFolder flag +- [05a5e45c] Add Folder.CreateVM method +- [4d5eb080] Add VirtualDiskManager wrapper +- [6b4744ac] Move waitForTask method to Client type +- [7e4d047d] Remove embedded ClientFlag +- [a16bada5] Store debug logs on disk +- [e1d7c5b0] Only care about guest.ipAddress property for -waitip +- [647bd102] Use cli flag types for host, pool and datastore +- [14d27b9f] Add cli HostSystemFlag +- [920a5c8a] Add cli ResourcePoolFlag +- [0f76226c] Cache Datastore lookup +- [7bb22ee0] Add govmomi.ResourcePool type +- [6ffac6fc] Wait for the guest to get an IP address +- [2c361e75] Import datastore command package +- [5a68e03c] Add datastore.download command +- [135eb434] Add datastore.upload command +- [02f40085] Add datastore.delete command +- [a25d7233] Add datastore.mkdir command +- [d1f9dad7] Add cli DatastorePathFlag +- [27789049] Add cli DatastoreFlag +- [ea66997e] Add Datastore URL, Upload/Download File methods +- [3c630d4d] Add FileManager wrapper +- [68ca1c21] Unembed ServiceContent in govmomi.Client +- [57dd4153] Enable/disable VNC from govc +- [002cb1dc] Rename field Ref -> Self +- [5a3968ad] Add generic list command +- [31664dcf] Assign reference to self in managed objects +- [99809e14] Include reference to self in managed objects +- [96b65720] Rely on response to determine managed object type +- [dcfd55a6] Include type registry for managed objects +- [46c8fce8] Load complete object for json output +- [ceb3cfa2] Use search flag from power command +- [1e19e548] Add vm.info, host.info commands +- [979d8c48] Split govc/vm/command.go +- [24ce0371] Add output flag +- [32693cf3] Initial stab at listing VMs +- [59734757] Add datacenter flag +- [382bf2bc] More verbosity +- [e9a6152d] Allow embedding of flag types +- [2d2386dc] Move client flag to flags pkg +- [c2f5e99b] Nesting of flags through reflection +- [6d6f9baa] Add SearchIndex wrapper +- [4e06b8ae] govc cli skeleton +- [444617bb] Add power on/off and reset functions to VirtualMachine +- [a1377afa] Add compute resource struct +- [b6aceec1] Add virtual machine struct +- [415f4cd9] Add network struct +- [a7b60eb8] Add datastore struct +- [18ec5f35] Function to retrieve datacenter folders +- [cebbf289] Retrieve only childEntity property for folder +- [c7b42438] Add folder and datacenter types +- [00dce928] Allow custom request for mo.RetrieveProperties +- [1ac7f6df] Embed ServiceContent type in govmomi.Client +- [887b482e] Use cookiejar in soap client +- [3b674be4] Add basic client structure +- [79f0006e] Don't use pointer for enum (string) fields +- [29b2981c] Move generated enum types to their own file +- [5a0e65e5] Import scripts used for code generation +- [71c53d0e] Initial import +- [6081afb9] Add Apache license +- [ff8c717d] Import modifications to xml package +- [57091273] Import Go LICENSE file +- [d5645253] Import encoding/xml from Go 1.3.1 diff --git a/vendor/github.com/vmware/govmomi/CONTRIBUTING.md b/vendor/github.com/vmware/govmomi/CONTRIBUTING.md index f6645cbf4f..038e5321b7 100644 --- a/vendor/github.com/vmware/govmomi/CONTRIBUTING.md +++ b/vendor/github.com/vmware/govmomi/CONTRIBUTING.md @@ -1,101 +1,197 @@ -# Contributing to govmomi +# Contributing to `govmomi` ## Getting started First, fork the repository on GitHub to your personal account. -Note that _GOPATH_ can be any directory, the example below uses _$HOME/govmomi_. -Change _$USER_ below to your github username if they are not the same. +Change `$USER` in the examples below to your Github username if they are not the +same. -``` shell -export GOPATH=$HOME/govmomi -go get github.com/vmware/govmomi -cd $GOPATH/src/github.com/vmware/govmomi -git config push.default nothing # anything to avoid pushing to vmware/govmomi by default +```bash +git clone https://github.com/vmware/govmomi.git && cd govmomi + +# prevent accidentally pushing to vmware/govmomi +git config push.default nothing git remote rename origin vmware + +# add your fork git remote add $USER git@github.com:$USER/govmomi.git -git fetch $USER + +git fetch -av ``` -## Installing from source - -Compile the govmomi libraries and install govc using: - -``` shell -go install -v github.com/vmware/govmomi/govc -``` - -Note that **govc/build.sh** is only used for building release binaries. - -## Contribution flow +## Contribution Flow This is a rough outline of what a contributor's workflow looks like: +- Create an issue describing the feature/fix - Create a topic branch from where you want to base your work. - Make commits of logical units. - Make sure your commit messages are in the proper format (see below). -- Update CHANGELOG.md and/or govc/CHANGELOG.md when appropriate. - Push your changes to a topic branch in your fork of the repository. -- Submit a pull request to vmware/govmomi. +- Submit a pull request to `vmware/govmomi`. -Example: +See [below](#format-of-the-commit-message) for details on commit best practices +and **supported prefixes**, e.g. `govc: `. -``` shell -git checkout -b my-new-feature vmware/master -git commit -a -git push $USER my-new-feature +> **Note:** If you are new to Git(hub) check out [Git rebase, squash...oh +> my!](https://www.mgasch.com/2021/05/git-basics/) for more details on how to +> successfully contribute to an open source project. + +### Example 1 - Fix a Bug in `govmomi` + +```bash +git checkout -b issue- main +git add +git commit -m "fix: ..." -m "Closes: #" +git push $USER issue- ``` -### Stay in sync with upstream +### Example 2 - Add a new (non-breaking) API to `govmomi` -When your branch gets out of sync with the vmware/master branch, use the following to update: +```bash +git checkout -b issue- main +git add +git commit -m "Add API ..." -m "Closes: #" +git push $USER issue- +``` -``` shell -git checkout my-new-feature +### Example 3 - Add a Feature to `govc` + +```bash +git checkout -b issue- main +git add +git commit -m "govc: Add feature ..." -m "Closes: #" +git push $USER issue- +``` +**Note**: +To register the new `govc` command package, add a blank `_` import to `govmomi/govc/main.go`. + +### Example 4 - Fix a Bug in `vcsim` + +```bash +git checkout -b issue- main +git add +git commit -m "vcsim: Fix ..." -m "Closes: #" +git push $USER issue- +``` + +### Example 5 - Document Breaking (API) Changes + +Breaking changes, e.g. to the `govmomi` APIs, are highlighted in the `CHANGELOG` +and release notes when the keyword `BREAKING:` is used in the commit message +body. + +The text after `BREAKING:` is used in the corresponding highlighted section. +Thus these details should be stated at the body of the commit message. +Multi-line strings are supported. + +```bash +git checkout -b issue- main +git add +cat << EOF | git commit -F - +Add ctx to funcXYZ + +This commit introduces context.Context to function XYZ +Closes: #1234 + +BREAKING: Add ctx to funcXYZ() +EOF + +git push $USER issue- +``` + +### Stay in sync with Upstream + +When your branch gets out of sync with the main branch, use the +following to update (rebase): + +```bash +git checkout issue- git fetch -a -git rebase vmware/master -git push --force-with-lease $USER my-new-feature +git rebase main +git push --force-with-lease $USER issue- ``` -### Updating pull requests +### Updating Pull Requests -If your PR fails to pass CI or needs changes based on code review, you'll most likely want to squash these changes into -existing commits. +If your PR fails to pass CI or needs changes based on code review, it's ok to +add more commits stating the changes made, e.g. "Address review comments". This +is to assist the reviewer(s) to easily detect and review the recent changes. -If your pull request contains a single commit or your changes are related to the most recent commit, you can simply -amend the commit. +In case of small PRs, it's ok to squash and force-push (see further below) +directly instead. -``` shell +```bash +# incorporate review feedback git add . -git commit --amend -git push --force-with-lease $USER my-new-feature -``` -If you need to squash changes into an earlier commit, you can use: - -``` shell -git add . +# create a fixup commit which will be merged into your (original) git commit --fixup -git rebase -i --autosquash vmware/master -git push --force-with-lease $USER my-new-feature +git push $USER issue- ``` -Be sure to add a comment to the PR indicating your new changes are ready to review, as github does not generate a -notification when you git push. +Be sure to add a comment to the PR indicating your new changes are ready to +review, as Github does not generate a notification when you git push. -### Code style +Once the review is complete, squash and push your final commit(s): -The coding style suggested by the Golang community is used in govmomi. See the +```bash +# squash all commits into one +# --autosquash will automatically detect and merge fixup commits +git rebase -i --autosquash main +git push --force-with-lease $USER issue- +``` + +### Code Style + +The coding style suggested by the Go community is used in `govmomi`. See the [style doc](https://github.com/golang/go/wiki/CodeReviewComments) for details. -Try to limit column width to 120 characters for both code and markdown documents such as this one. +Try to limit column width to 120 characters for both code and markdown documents +such as this one. ### Format of the Commit Message -We follow the conventions on [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/). +We follow the conventions described in [How to Write a Git Commit +Message](http://chris.beams.io/posts/git-commit/). -Be sure to include any related GitHub issue references in the commit message. +Be sure to include any related GitHub issue references in the commit message, +e.g. `Closes: #`. + +The [`CHANGELOG.md`](./CHANGELOG.md) and release page uses **commit message +prefixes** for grouping and highlighting. A commit message that +starts with `[prefix:] ` will place this commit under the respective +section in the `CHANGELOG`. + +The following example creates a commit referencing the `issue: 1234` and puts +the commit message in the `govc` `CHANGELOG` section: + +```bash +git commit -s -m "govc: Add CLI command X" -m "Closes: #1234" +``` + +Currently the following prefixes are used: + +- `api:` - Use for API-related changes +- `govc:` - Use for changes to `govc` CLI +- `vcsim:` - Use for changes to vCenter Simulator +- `chore:` - Use for repository related activities +- `fix:` - Use for bug fixes +- `docs:` - Use for changes to the documentation +- `examples:` - Use for changes to examples + +If your contribution falls into multiple categories, e.g. `api` and `vcsim` it +is recommended to break up your commits using distinct prefixes. + +### Running CI Checks and Tests +You can run both `make check` and `make test` from the top level of the +repository. + +While `make check` will catch formatting and import errors, it will not apply +any fixes. The developer is expected to do that. ## Reporting Bugs and Creating Issues -When opening a new issue, try to roughly follow the commit message format conventions above. +When opening a new issue, try to roughly follow the commit message format +conventions above. diff --git a/vendor/github.com/vmware/govmomi/CONTRIBUTORS b/vendor/github.com/vmware/govmomi/CONTRIBUTORS index 6a421d0991..03ca7c2f9e 100644 --- a/vendor/github.com/vmware/govmomi/CONTRIBUTORS +++ b/vendor/github.com/vmware/govmomi/CONTRIBUTORS @@ -5,104 +5,279 @@ Abhijeet Kasurde abrarshivani +Adam Chalkley +Adam Fowler Adam Shannon +Akanksha Panse +Al Biheiri Alessandro Cortiana +Alex Alex Bozhenko Alex Ellis (VMware) +Aligator <8278538+yet-another-aligator@users.noreply.github.com> Alvaro Miranda Amanda H. L. de Andrade +amanpaha Amit Bathla amit bezalel Andrew Andrew Chin Andrew Kutz +Andrey Klimentyev Anfernee Yongkun Gui angystardust aniketGslab +Ankit Gohil +Ankit Vaidya +Ankur Huralikoppi +Anna Carrigan +Antony Saba +Ariel Chinn Arran Walker +Artem Anisimov +Arunesh Pandey Aryeh Weinreb +Augy StClair Austin Parker Balu Dontu bastienbc +Ben Corrie +Ben Vickers +Benjamin Davini +Benjamin Peterson +Benjamin Vickers +Bhavya Choudhary Bob Killen Brad Fitzpatrick +Brian McClain +Brian Rak +brian57860 Bruce Downs -Cédric Blomart +Bruno Meneguello <1322552+bkmeneguello@users.noreply.github.com> +Bryan Venteicher +C S P Nanda +Carsten Grohmann +Cheng Cheng +Chethan Venkatesh +Choudhury Sarada Prasanna Nanda Chris Marchesi Christian Höltje +Christian Schlotter Clint Greenwood +cpiment CuiHaozhi +Cédric Blomart +Dan Ilan +Dan Norris +Daniel Frederick Crisman +Daniel Mueller +Danielle Barda Danny Lockard +Dave Gress +Dave Smith-Uchida Dave Tucker -Davide Agnello +David Gress David Stark +Davide Agnello Davinder Kumar +Defa +demarey Deric Crago +Deyan Popov +Dinesh Bhat <35480850+dbhat-arkin@users.noreply.github.com> +ditsuke +Divyen Patel +Dnyanesh Gate Doug MacEachern +East <60801291+houfangdong@users.noreply.github.com> Eloy Coto +Eng Zer Jun +Eric Edens +Eric Graham <16710890+Pheric@users.noreply.github.com> Eric Gray Eric Yutao Erik Hollensbe +Erik Lund +Essodjolo KAHANAM Ethan Kaley +Evan Chu Fabio Rapposelli -Faiyaz Ahmed +fabriziopandini +Faiyaz Ahmed +Federico Pellegatta <12744504+federico-pellegatta@users.noreply.github.com> forkbomber +François Rigault freebsdly Gavin Gray Gavrie Philipson George Hicken +George Hicken Gerrit Renker gthombare +guoguangwu +Hakan Halil +HakanSunay Hasan Mahmood +Haydon Ryan +Heiko Reese Henrik Hodne +hkumar +Hrabur Stoyanov +hui luo +Ian Eyberg Isaac Rodman +Ivan Mikushin Ivan Porto Carrero James King +James Peach Jason Kincl Jeremy Canady jeremy-clerc Jiatong Wang -João Pereira +jingyizPensando Jonas Ausevicius Jorge Sevilla +Joseph LeBlanc +João Pereira +Julien PILLON +Justin J. Novack kayrus +Keenan Brock Kevin George +Kiril Karaatanassov +Knappek +Kristian Alvestad +Lars Lehtonen +Leslie Wang leslie-qiwa +Lintong Jiang +Liping Xue +liron.levin Louie Jiang +Lubron Zhan +Luther Monson +Madanagopal Arunachalam +makelarisjr <8687447+makelarisjr@users.noreply.github.com> +Manuel Grandeit maplain Marc Carmier +Marcus Tan Maria Ntalla Marin Atanasov Nikolov +Mario Trangoni +Mark Dechiaro +Mark Peek +Mark Rexwinkel +martin Matt Clay -Matthew Cosgrove +Matt Moore Matt Moriarity +Matthew Cosgrove +Mayank Bhatt +mbhadale +Merlijn Sebrechts Mevan Samaratunga +Michael Gasch Michal Jankowski +Mike Schinkel +Mincho Tonev mingwei Nicolas Lamirault +nikhaild <84156354+nikhaild@users.noreply.github.com> +Nikhil Kathare +Nikhil R Deshpande +Nikolas Grottendieck +Nils Elde +nirbhay +Nobuhiro MIKI +Om Kumar Omar Kohl Parham Alvani +Parveen Chahal +Paul Martin <25058109+rawstorage@users.noreply.github.com> Pierre Gronlier Pieter Noordhuis +pradeepj <50135054+pradeep288@users.noreply.github.com> +Pranshu Jain prydin +rconde01 +rHermes +Rianto Wahyudi +Ricardo Katz +rmcqueen +Robin Watkins Rowan Jacobs +Roy Ling +rsikdar runner.mei +Ryan Johnson +S R Ashrith S.Çağlar Onur +Saad Malik +Sam Zhu +samzhu333 <45263849+samzhu333@users.noreply.github.com> +Sandeep Pissay Srinivasa Rao +schmikei +Scott Holden Sergey Ignatov +serokles +shahra +Shalini Bhaskara +Shaozhen Ding +Shawn Neal +shylasrinivas +sky-joker +smaftoul +smahadik +Sten Feldman +Stepan Mazurov Steve Purcell +Stoyan Zhelyazkov +Sudhindra Aithal +SUMIT AGRAWAL +Sunny Carter +syuparn Takaaki Furukawa Tamas Eger +Tanay Kothari tanishi Ted Zlatanov +Thad Craft Thibaut Ackermann +Tim McNamara +Tjeu Kayim <15987676+TjeuKayim@users.noreply.github.com> +Toomas Pelberg Trevor Dawe +tshihad +Ueli Banholzer Uwe Bessle Vadim Egorov +Vamshik Shetty Vikram Krishnamurthy +Vipul Kotkar +volanja Volodymyr Bobyr +Waldek Maleska +William Lam Witold Krecicki +xing-yang +xinyanw409 Yang Yang +yangxi +Yann Hodique +Yash Nitin Desai +Yassine TIJANI +Yi Jiang +yiyingy +ykakarap +Yogesh Sobale <6104071+ysobale@users.noreply.github.com> +Your Name +Yue Yin +Yun Zhou Yuya Kusakabe -Zacharias Taubert +Zach G Zach Tucker +Zacharias Taubert Zee Yang +zyuxin +Кузаков Евгений diff --git a/vendor/github.com/vmware/govmomi/Dockerfile b/vendor/github.com/vmware/govmomi/Dockerfile deleted file mode 100644 index 4f84fadaaf..0000000000 --- a/vendor/github.com/vmware/govmomi/Dockerfile +++ /dev/null @@ -1,4 +0,0 @@ -FROM scratch -LABEL maintainer="fabio@vmware.com" -COPY govc / -ENTRYPOINT [ "/govc" ] \ No newline at end of file diff --git a/vendor/github.com/vmware/govmomi/Dockerfile.govc b/vendor/github.com/vmware/govmomi/Dockerfile.govc new file mode 100644 index 0000000000..e7d6766b01 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/Dockerfile.govc @@ -0,0 +1,45 @@ +# Create a builder container +# golang:1.18.0-buster amd64 +FROM golang@sha256:7d39537344486528f8cdb3bd8adb98ab7f0f4236044b6944fed8631da35a4ce5 AS build +WORKDIR /go/src/app + +# Create appuser to isolate potential vulnerabilities +# See https://stackoverflow.com/a/55757473/12429735 +ENV USER=appuser +ENV UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + "${USER}" + +# Create a new tmp directory so no bad actors can manipulate it +RUN mkdir /temporary-tmp-directory && chmod 777 /temporary-tmp-directory + +############################################################################### +# Final stage +FROM scratch + +# Allow container to use latest TLS certificates +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Copy over appuser to run as non-root +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group + +# Copy over the /tmp directory for golang/os.TmpDir +COPY --chown=appuser --from=build /temporary-tmp-directory /tmp + +# Copy application from external build +COPY govc /govc + +# Run all commands as non-root +USER appuser:appuser + +# session cache, etc +ENV GOVMOMI_HOME=/tmp + +# Set CMD to application with container defaults +CMD ["/govc"] diff --git a/vendor/github.com/vmware/govmomi/Dockerfile.vcsim b/vendor/github.com/vmware/govmomi/Dockerfile.vcsim new file mode 100644 index 0000000000..141de0ff2e --- /dev/null +++ b/vendor/github.com/vmware/govmomi/Dockerfile.vcsim @@ -0,0 +1,47 @@ +# Create a builder container +# golang:1.18.0-buster amd64 +FROM golang@sha256:7d39537344486528f8cdb3bd8adb98ab7f0f4236044b6944fed8631da35a4ce5 AS build +WORKDIR /go/src/app + +# Create appuser to isolate potential vulnerabilities +# See https://stackoverflow.com/a/55757473/12429735 +ENV USER=appuser +ENV UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + "${USER}" + +# Create a new tmp directory so no bad actors can manipulate it +RUN mkdir /temporary-tmp-directory && chmod 777 /temporary-tmp-directory + +############################################################################### +# Final stage +FROM scratch + +# Run all commands as non-root +USER appuser:appuser + +# Allow container to use latest TLS certificates +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# Copy over appuser to run as non-root +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group + +# Copy over the /tmp directory for golang/os.TmpDir +COPY --chown=appuser --from=build /temporary-tmp-directory /tmp + +# Expose application port +EXPOSE 8989 + +# Copy application from external build +COPY vcsim /vcsim + +# Set entrypoint to application with container defaults +ENTRYPOINT [ "/vcsim" ] +CMD ["-l", "0.0.0.0:8989"] diff --git a/vendor/github.com/vmware/govmomi/Gopkg.lock b/vendor/github.com/vmware/govmomi/Gopkg.lock deleted file mode 100644 index f45057fb22..0000000000 --- a/vendor/github.com/vmware/govmomi/Gopkg.lock +++ /dev/null @@ -1,60 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "improvements" - digest = "1:b183578c34fabccaf65f1a57d2efeec2086abdce1446978d69ab3a0016cb750c" - name = "github.com/davecgh/go-xdr" - packages = ["xdr2"] - pruneopts = "NUT" - revision = "4930550ba2e22f87187498acfd78348b15f4e7a8" - source = "https://github.com/rasky/go-xdr" - -[[projects]] - digest = "1:1ab18cf8c2084968d6dca0dd46fbda9efba08664ecd7957b63c7ca57bb2455df" - name = "github.com/google/uuid" - packages = ["."] - pruneopts = "NUT" - revision = "6a5e28554805e78ea6141142aba763936c4761c0" - -[[projects]] - branch = "govmomi" - digest = "1:f49ed6cb2129e9a3ce9dde5037cb243b5849c0ec0c7973b9d1e987872d8b8cc6" - name = "github.com/kr/pretty" - packages = ["."] - pruneopts = "NUT" - revision = "2ee9d7453c02ef7fa518a83ae23644eb8872186a" - source = "https://github.com/dougm/pretty" - -[[projects]] - branch = "master" - digest = "1:c3a7836b5904db0f8b609595b619916a6831cb35b8b714aec39f96d00c6155d8" - name = "github.com/kr/text" - packages = ["."] - pruneopts = "NUT" - revision = "7cafcd837844e784b526369c9bce262804aebc60" - -[[projects]] - branch = "master" - digest = "1:4bea31865971675c482ed875caeabe7d2182dcb47d52900b7da5236d66dc9970" - name = "github.com/vmware/vmw-guestinfo" - packages = [ - "bdoor", - "message", - "vmcheck", - ] - pruneopts = "NUT" - revision = "25eff159a728be87e103a0b8045e08273f4dbec4" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/davecgh/go-xdr/xdr2", - "github.com/google/uuid", - "github.com/kr/pretty", - "github.com/vmware/vmw-guestinfo/message", - "github.com/vmware/vmw-guestinfo/vmcheck", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/vmware/govmomi/Gopkg.toml b/vendor/github.com/vmware/govmomi/Gopkg.toml deleted file mode 100644 index 4c4d6765e6..0000000000 --- a/vendor/github.com/vmware/govmomi/Gopkg.toml +++ /dev/null @@ -1,19 +0,0 @@ -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# Refer to https://github.com/toml-lang/toml for detailed TOML docs. - -[prune] - non-go = true - go-tests = true - unused-packages = true - -[[constraint]] - branch = "improvements" - name = "github.com/davecgh/go-xdr" - source = "https://github.com/rasky/go-xdr" - -[[constraint]] - branch = "govmomi" - name = "github.com/kr/pretty" - source = "https://github.com/dougm/pretty" diff --git a/vendor/github.com/vmware/govmomi/Makefile b/vendor/github.com/vmware/govmomi/Makefile index ee17fe586f..0f31649af8 100644 --- a/vendor/github.com/vmware/govmomi/Makefile +++ b/vendor/github.com/vmware/govmomi/Makefile @@ -1,29 +1,153 @@ -.PHONY: test +# Copyright (c) 2021 VMware, Inc. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 -all: check test +# If you update this file, please follow +# https://www.thapaliya.com/en/writings/well-documented-makefiles/ -check: goimports govet +# Ensure Make is run with bash shell as some syntax below is bash-specific +SHELL := /usr/bin/env bash -goimports: - @echo checking go imports... - @command -v goimports >/dev/null 2>&1 || go get golang.org/x/tools/cmd/goimports - @! goimports -d . 2>&1 | egrep -v '^$$' +# Print the help/usage when make is executed without any other arguments +.DEFAULT_GOAL := help -govet: - @echo checking go vet... - @go tool vet -structtags=false -methods=false $$(find . -mindepth 1 -maxdepth 1 -type d -not -name vendor) -install: +## -------------------------------------- +## Help +## -------------------------------------- + +.PHONY: help +help: ## Display usage + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make [target] \033[36m\033[0m\n\nTargets:\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) + + +## -------------------------------------- +## Locations and programs +## -------------------------------------- + +# Directories +BIN_DIR := bin +TOOLS_DIR := hack/tools +TOOLS_BIN_DIR := $(TOOLS_DIR)/bin + +# Tooling binaries +GO ?= $(shell command -v go 2>/dev/null) +GOLANGCI_LINT := $(TOOLS_BIN_DIR)/golangci-lint + + +## -------------------------------------- +## Prerequisites +## -------------------------------------- + +# Do not proceed unless the go binary is present. +ifeq (,$(strip $(GO))) +$(error The "go" program cannot be found) +endif + + +## -------------------------------------- +## Linting and fixing linter errors +## -------------------------------------- + +.PHONY: lint +lint: ## Run all the lint targets + $(MAKE) lint-go-full + +GOLANGCI_LINT_FLAGS ?= --fast=true +.PHONY: lint-go +lint-go: $(GOLANGCI_LINT) ## Lint codebase + $(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_FLAGS) + +.PHONY: lint-go-full +lint-go-full: GOLANGCI_LINT_FLAGS = --fast=false --max-same-issues=200 +lint-go-full: lint-go ## Run slower linters to detect possible issues + +.PHONY: fix +fix: GOLANGCI_LINT_FLAGS = --fast=false --fix +fix: lint-go ## Tries to fix errors reported by lint-go-full target + +.PHONY: check +check: lint-go-full +check: ## Run linters + + +## -------------------------------------- +## Tooling Binaries +## -------------------------------------- + +TOOLING_BINARIES := $(GOLANGCI_LINT) +tools: $(TOOLING_BINARIES) ## Build tooling binaries +.PHONY: $(TOOLING_BINARIES) +$(TOOLING_BINARIES): + cd $(TOOLS_DIR); make $(@F) + + +## -------------------------------------- +## Build / Install +## -------------------------------------- +.PHONY: install +install: ## Install govc and vcsim $(MAKE) -C govc install $(MAKE) -C vcsim install -go-test: - GORACE=history_size=5 go test -timeout 5m -count 1 -race -v $(TEST_OPTS) ./... -govc-test: install - (cd govc/test && ./vendor/github.com/sstephenson/bats/libexec/bats -t .) +## -------------------------------------- +## Generate +## -------------------------------------- -test: go-test govc-test +.PHONY: mod +mod: ## Runs go mod tidy to validate modules + go mod tidy -v +.PHONY: mod-get +mod-get: ## Downloads and caches the modules + go mod download + +.PHONY: doc doc: install +doc: ## Generates govc USAGE.md ./govc/usage.sh > ./govc/USAGE.md + +.PHONY: generate-types +generate-types: ## Generate the types + $(MAKE) -C ./gen/ $@ + + +## -------------------------------------- +## Tests +## -------------------------------------- + +# Test options +TEST_COUNT ?= 1 +TEST_TIMEOUT ?= 5m +TEST_RACE_HISTORY_SIZE ?= 5 +GORACE ?= history_size=$(TEST_RACE_HISTORY_SIZE) + +ifeq (-count,$(findstring -count,$(TEST_OPTS))) +$(error Use TEST_COUNT to override this option) +endif + +ifeq (-race,$(findstring -race,$(TEST_OPTS))) +$(error The -race flag is enabled by default & cannot be specified in TEST_OPTS) +endif + +ifeq (-timeout,$(findstring -timeout,$(TEST_OPTS))) +$(error Use TEST_TIMEOUT to override this option) +endif + +.PHONY: go-test +go-test: ## Runs go unit tests with race detector enabled + GORACE=$(GORACE) CGO_ENABLED=1 $(GO) test \ + -count $(TEST_COUNT) \ + -race \ + -timeout $(TEST_TIMEOUT) \ + -v $(TEST_OPTS) \ + ./... + +.PHONY: govc-test +govc-test: install +govc-test: ## Runs govc bats tests + ./govc/test/images/update.sh + (cd govc/test && ./vendor/github.com/bats-core/bats-core/bin/bats -t .) + +.PHONY: test +test: go-test govc-test ## Runs go-test and govc-test diff --git a/vendor/github.com/vmware/govmomi/README.md b/vendor/github.com/vmware/govmomi/README.md index 1c31bbdda4..13ba3bf30e 100644 --- a/vendor/github.com/vmware/govmomi/README.md +++ b/vendor/github.com/vmware/govmomi/README.md @@ -1,94 +1,127 @@ -[![Build Status](https://travis-ci.org/vmware/govmomi.png?branch=master)](https://travis-ci.org/vmware/govmomi) -[![Go Report Card](https://goreportcard.com/badge/github.com/vmware/govmomi)](https://goreportcard.com/report/github.com/vmware/govmomi) + + +[![Build](https://github.com/vmware/govmomi/actions/workflows/govmomi-build.yaml/badge.svg)][ci-build] +[![Tests](https://github.com/vmware/govmomi/actions/workflows/govmomi-go-tests.yaml/badge.svg)][ci-tests] +[![Go Report Card](https://goreportcard.com/badge/github.com/vmware/govmomi)][go-report-card] +[![Latest Release](https://img.shields.io/github/release/vmware/govmomi.svg?logo=github&style=flat-square)][latest-release] +[![Go Reference](https://pkg.go.dev/badge/github.com/vmware/govmomi.svg)][go-reference] +[![go.mod Go version](https://img.shields.io/github/go-mod/go-version/vmware/govmomi)][go-version] # govmomi -A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter). +A Go library for interacting with VMware vSphere APIs (ESXi and/or vCenter Server). In addition to the vSphere API client, this repository includes: -* [govc](./govc) - vSphere CLI - -* [vcsim](./vcsim) - vSphere API mock framework - -* [toolbox](./toolbox) - VM guest tools framework +* [govc][govc] - vSphere CLI +* [vcsim][vcsim] - vSphere API mock framework +* [toolbox][toolbox] - VM guest tools framework ## Compatibility -This library is built for and tested against ESXi and vCenter 6.0, 6.5 and 6.7. +This library supports vCenter Server and ESXi versions following the [VMware Product Lifecycle Matrix][reference-lifecycle]. -It may work with versions 5.5 and 5.1, but neither are officially supported. +Product versions that are end of support may work, but are not officially supported. ## Documentation -The APIs exposed by this library very closely follow the API described in the [VMware vSphere API Reference Documentation][apiref]. -Refer to this document to become familiar with the upstream API. +The APIs exposed by this library closely follow the API described in the [VMware vSphere API Reference Documentation][reference-api]. Refer to the documentation to become familiar with the upstream API. -The code in the `govmomi` package is a wrapper for the code that is generated from the vSphere API description. -It primarily provides convenience functions for working with the vSphere API. -See [godoc.org][godoc] for documentation. - -[apiref]:http://pubs.vmware.com/vsphere-6-5/index.jsp#com.vmware.wssdk.apiref.doc/right-pane.html -[godoc]:http://godoc.org/github.com/vmware/govmomi +The code in the `govmomi` package is a wrapper for the code that is generated from the vSphere API description. It primarily provides convenience functions for working with the vSphere API. See [godoc.org][reference-godoc] for documentation. ## Installation -```sh -go get -u github.com/vmware/govmomi -``` +### Binaries and Docker Images for `govc` and `vcsim` + +Installation instructions, released binaries, and Docker images are documented in the respective README files of [`govc`][govc] and [`vcsim`][vcsim]. ## Discussion -Contributors and users are encouraged to collaborate using GitHub issues and/or -[Slack](https://vmwarecode.slack.com/messages/govmomi). -Access to Slack requires a [VMware {code} membership](https://code.vmware.com/join/). +The project encourages the community to collaborate using GitHub [issues][govmomi-github-issues], GitHub [discussions][govmomi-github-discussions], and [Slack][slack-channel]. + +> **Note** +> Access to Slack requires a free [VMware {code}][slack-join] developer program membership. ## Status -Changes to the API are subject to [semantic versioning](http://semver.org). +Changes to the API are subject to [semantic versioning][reference-semver]. -Refer to the [CHANGELOG](CHANGELOG.md) for version to version changes. +Refer to the [CHANGELOG][govmomi-changelog] for version to version changes. -## Projects using govmomi +## Notable Projects Using govmomi -* [Docker Machine](https://github.com/docker/machine/tree/master/drivers/vmwarevsphere) +* [collectd-vsphere][project-travisci-collectd-vsphere] +* [Docker LinuxKit][project-docker-linuxKit] +* [Elastic Agent VMware vSphere integration][project-elastic-agent] +* [Gru][project-gru] +* [Juju][project-juju] +* [Jupiter Brain][project-travisci-jupiter-brain] +* [Kubernetes vSphere Cloud Provider][project-k8s-cloud-provider] +* [Kubernetes Cluster API][project-k8s-cluster-api] +* [OPS][project-nanovms-ops] +* [OpenTelemetry Collector Contrib][opentelemetry-collector-contrib] +* [Packer Plugin for VMware vSphere][project-hashicorp-packer-plugin-vsphere] +* [Rancher][project-rancher] +* [Terraform Provider for VMware vSphere][project-hashicorp-terraform-provider-vsphere] +* [Telegraf][project-influxdata-telegraf] +* [VMware Event Broker Appliance][project-vmware-veba] +* [VMware vSphere Integrated Containers Engine][project-vmware-vic] +* [VMware vSphere 7.0][project-vmware-vsphere] -* [Docker InfraKit](https://github.com/docker/infrakit/tree/master/pkg/provider/vsphere) +## Related Projects -* [Docker LinuxKit](https://github.com/linuxkit/linuxkit/tree/master/src/cmd/linuxkit) - -* [Kubernetes](https://github.com/kubernetes/kubernetes/tree/master/pkg/cloudprovider/providers/vsphere) - -* [Kubernetes Cloud Provider](https://github.com/kubernetes/cloud-provider-vsphere) - -* [Kubernetes Cluster API](https://github.com/kubernetes-sigs/cluster-api-provider-vsphere) - -* [Kubernetes kops](https://github.com/kubernetes/kops/tree/master/upup/pkg/fi/cloudup/vsphere) - -* [Terraform](https://github.com/terraform-providers/terraform-provider-vsphere) - -* [Packer](https://github.com/jetbrains-infra/packer-builder-vsphere) - -* [VMware VIC Engine](https://github.com/vmware/vic) - -* [Travis CI](https://github.com/travis-ci/jupiter-brain) - -* [collectd-vsphere](https://github.com/travis-ci/collectd-vsphere) - -* [Gru](https://github.com/dnaeon/gru) - -* [Libretto](https://github.com/apcera/libretto/tree/master/virtualmachine/vsphere) - -* [Telegraf](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/vsphere) - -* [Open Storage](https://github.com/libopenstorage/openstorage/tree/master/pkg/storageops/vsphere) - -## Related projects - -* [rbvmomi](https://github.com/vmware/rbvmomi) - -* [pyvmomi](https://github.com/vmware/pyvmomi) +* [go-vmware-nsxt][reference-go-vmware-nsxt] +* [pyvmomi][reference-pyvmomi] +* [rbvmomi][reference-rbvmomi] ## License -govmomi is available under the [Apache 2 license](LICENSE.txt). +govmomi is available under the [Apache 2 License][govmomi-license]. + +## Name + +Pronounced: _go·​v·​mom·​ie_ + +Follows pyvmomi and rbvmomi: language prefix + the vSphere acronym "VM Object Management Infrastructure". + +[//]: Links + +[ci-build]: https://github.com/vmware/govmomi/actions/workflows/govmomi-build.yaml +[ci-tests]: https://github.com/vmware/govmomi/actions/workflows/govmomi-go-tests.yaml +[latest-release]: https://github.com/vmware/govmomi/releases/latest +[govc]: govc/README.md +[govmomi-github-issues]: https://github.com/vmware/govmomi/issues +[govmomi-github-discussions]: https://github.com/vmware/govmomi/discussions +[govmomi-changelog]: CHANGELOG.md +[govmomi-license]: LICENSE.txt +[go-reference]: https://pkg.go.dev/github.com/vmware/govmomi +[go-report-card]: https://goreportcard.com/report/github.com/vmware/govmomi +[go-version]: https://github.com/vmware/govmomi +[opentelemetry-collector-contrib]: https://github.com/open-telemetry/opentelemetry-collector-contrib +[project-docker-linuxKit]: https://github.com/linuxkit/linuxkit/tree/master/src/cmd/linuxkit +[project-elastic-agent]: https://github.com/elastic/integrations/tree/main/packages/vsphere +[project-gru]: https://github.com/dnaeon/gru +[project-hashicorp-packer-plugin-vsphere]: https://github.com/hashicorp/packer-plugin-vsphere +[project-hashicorp-terraform-provider-vsphere]: https://github.com/hashicorp/terraform-provider-vsphere +[project-influxdata-telegraf]: https://github.com/influxdata/telegraf/tree/master/plugins/inputs/vsphere +[project-juju]: https://github.com/juju/juju +[project-k8s-cloud-provider]: https://github.com/kubernetes/cloud-provider-vsphere +[project-k8s-cluster-api]: https://github.com/kubernetes-sigs/cluster-api-provider-vsphere +[project-nanovms-ops]: https://github.com/nanovms/ops +[project-rancher]: https://github.com/rancher/rancher/blob/master/pkg/api/norman/customization/vsphere/listers.go +[project-travisci-collectd-vsphere]: https://github.com/travis-ci/collectd-vsphere +[project-travisci-jupiter-brain]: https://github.com/travis-ci/jupiter-brain +[project-vmware-veba]: https://github.com/vmware-samples/vcenter-event-broker-appliance/tree/development/vmware-event-router +[project-vmware-vic]: https://github.com/vmware/vic +[project-vmware-vsphere]: https://docs.vmware.com/en/VMware-vSphere/7.0/rn/vsphere-esxi-vcenter-server-7-vsphere-with-kubernetes-release-notes.html +[reference-api]: https://developer.vmware.com/apis/968/vsphere +[reference-godoc]: http://godoc.org/github.com/vmware/govmomi +[reference-go-vmware-nsxt]: https://github.com/vmware/go-vmware-nsxt +[reference-lifecycle]: https://lifecycle.vmware.com +[reference-pyvmomi]: https://github.com/vmware/pyvmomi +[reference-rbvmomi]: https://github.com/vmware/rbvmomi +[reference-semver]: http://semver.org +[slack-join]: https://developer.vmware.com/join/ +[slack-channel]: https://vmwarecode.slack.com/messages/govmomi +[toolbox]: toolbox/README.md +[vcsim]: vcsim/README.md diff --git a/vendor/github.com/vmware/govmomi/RELEASE.md b/vendor/github.com/vmware/govmomi/RELEASE.md new file mode 100644 index 0000000000..58b978a50f --- /dev/null +++ b/vendor/github.com/vmware/govmomi/RELEASE.md @@ -0,0 +1,109 @@ +# How to create a `govmomi` Release on Github + +> **Note** +> +> The steps outlined in this document can only be performed by maintainers or +> administrators of this project. + +The release automation is based on Github +[Actions](https://github.com/features/actions) and has been improved over time +to simplify the experience for creating `govmomi` releases. + +The Github Actions release [workflow](.github/workflows/govmomi-release.yaml) +uses [`goreleaser`](http://goreleaser.com/) and automatically creates/pushes: + +- Release artifacts for `govc` and `vcsim` to the + [release](https://github.com/vmware/govmomi/releases) page, including + `LICENSE.txt`, `README` and `CHANGELOG` +- Docker images for `vmware/govc` and `vmware/vcsim` to Docker Hub +- Source code + +Releases are not tagged on the `main` branch, but a dedicated release branch, for example `release-0.35`. + +### Verify `main` branch is up to date with the remote + +```console +git checkout main +git fetch -avp +git diff main origin/main + +# if your local and remote branches diverge run +git pull origin/main +``` + +> **Warning** +> +> These steps assume `origin` to point to the remote +> `https://github.com/vmware/govmomi`, respectively +> `git@github.com:vmware/govmomi`. + +### Create a release branch + +For new releases, create a release branch from the most recent commit in +`main`, e.g. `release-0.35`. + +```console +export RELEASE_BRANCH=release-0.35 +git checkout -b ${RELEASE_BRANCH} +``` + +For maintenance/patch releases on **existing** release branches, simply checkout the existing +release branch and add commits to the existing release branch. + +### Verify `make docs` and `CONTRIBUTORS` are up to date + +> **Warning** +> +> Run the following commands and commit any changes to the release branch before +> proceeding with the release. + +```console +make doc +./scripts/contributors.sh +if [ -z "$(git status --porcelain)" ]; then + echo "working directory clean: proceed with release" +else + echo "working directory dirty: please commit changes" +fi + +# perform git add && git commit ... in case there were changes +``` + +### Push the release branch + +> **Warning** +> +> Do not create a tag as this will be done by the release automation. + +The final step is pushing the new/updated release branch. + +```console +git push origin ${RELEASE_BRANCH} +``` + +### Create a release in the Github UI + +Open the `govmomi` Github [repository](https://github.com/vmware/govmomi) and +navigate to `Actions -> Workflows -> Release`. + +Click `Run Workflow` which opens a dropdown list. + +Select the new/updated branch, e.g. `release-0.35`, i.e. **not** the `main` +branch. + +Specify a semantic `tag` to associate with the release, e.g. `v0.35.0`. + +> **Warning** +> +> This tag **must not** exist or the release will fail during the validation +> phase. + +By default, a dry-run is performed to rule out most (but not all) errors during +a release. If you do not want to perform a dry-run, e.g. to finally create a +release, deselect the `Verify release workflow ...` checkbox. + +Click `Run Workflow` to kick off the workflow. + +After successful completion and if the newly created `tag` is the **latest** +(semantic version sorted) tag in the repository, a PR is automatically opened +against the `main` branch to update the `CHANGELOG`. diff --git a/vendor/github.com/vmware/govmomi/USAGE.md b/vendor/github.com/vmware/govmomi/USAGE.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/github.com/vmware/govmomi/client.go b/vendor/github.com/vmware/govmomi/client.go index ad49fe6bf7..5becedd489 100644 --- a/vendor/github.com/vmware/govmomi/client.go +++ b/vendor/github.com/vmware/govmomi/client.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 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 +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, @@ -19,7 +19,7 @@ This package is the root package of the govmomi library. The library is structured as follows: -Package vim25 +# Package vim25 The minimal usable functionality is available through the vim25 package. It contains subpackages that contain generated types, managed objects, and all @@ -30,25 +30,25 @@ The vim25 package itself contains a client structure that is passed around throughout the entire library. It abstracts a session and its immutable state. See the vim25 package for more information. -Package session +# Package session The session package contains an abstraction for the session manager that allows a user to login and logout. It also provides access to the current session (i.e. to determine if the user is in fact logged in) -Package object +# Package object The object package contains wrappers for a selection of managed objects. The constructors of these objects all take a *vim25.Client, which they pass along to derived objects, if applicable. -Package govc +# Package govc The govc package contains the govc CLI. The code in this tree is not intended to be used as a library. Any functionality that govc contains that _could_ be used as a library function but isn't, _should_ live in a root level package. -Other packages +# Other packages Other packages, such as "event", "guest", or "license", provide wrappers for the respective subsystems. They are typically not needed in normal workflows so diff --git a/vendor/github.com/vmware/govmomi/history/collector.go b/vendor/github.com/vmware/govmomi/history/collector.go new file mode 100644 index 0000000000..9b25ea85a1 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/history/collector.go @@ -0,0 +1,91 @@ +/* +Copyright (c) 2015 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 history + +import ( + "context" + + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +type Collector struct { + r types.ManagedObjectReference + c *vim25.Client +} + +func NewCollector(c *vim25.Client, ref types.ManagedObjectReference) *Collector { + return &Collector{ + r: ref, + c: c, + } +} + +// Reference returns the managed object reference of this collector +func (c Collector) Reference() types.ManagedObjectReference { + return c.r +} + +// Client returns the vim25 client used by this collector +func (c Collector) Client() *vim25.Client { + return c.c +} + +// Properties wraps property.DefaultCollector().RetrieveOne() and returns +// properties for the specified managed object reference +func (c Collector) Properties(ctx context.Context, r types.ManagedObjectReference, ps []string, dst interface{}) error { + return property.DefaultCollector(c.c).RetrieveOne(ctx, r, ps, dst) +} + +func (c Collector) Destroy(ctx context.Context) error { + req := types.DestroyCollector{ + This: c.r, + } + + _, err := methods.DestroyCollector(ctx, c.c, &req) + return err +} + +func (c Collector) Reset(ctx context.Context) error { + req := types.ResetCollector{ + This: c.r, + } + + _, err := methods.ResetCollector(ctx, c.c, &req) + return err +} + +func (c Collector) Rewind(ctx context.Context) error { + req := types.RewindCollector{ + This: c.r, + } + + _, err := methods.RewindCollector(ctx, c.c, &req) + return err +} + +func (c Collector) SetPageSize(ctx context.Context, maxCount int32) error { + req := types.SetCollectorPageSize{ + This: c.r, + MaxCount: maxCount, + } + + _, err := methods.SetCollectorPageSize(ctx, c.c, &req) + return err +} diff --git a/vendor/github.com/vmware/govmomi/internal/helpers.go b/vendor/github.com/vmware/govmomi/internal/helpers.go new file mode 100644 index 0000000000..41e533fd75 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/internal/helpers.go @@ -0,0 +1,141 @@ +/* +Copyright (c) 2020-2023 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 internal + +import ( + "context" + "fmt" + "net" + "net/http" + "net/url" + "os" + "path" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +const ( + vCenterHostGatewaySocket = "/var/run/envoy-hgw/hgw-pipe" + vCenterHostGatewaySocketEnv = "VCENTER_ENVOY_HOST_GATEWAY" +) + +// InventoryPath composed of entities by Name +func InventoryPath(entities []mo.ManagedEntity) string { + val := "/" + + for _, entity := range entities { + // Skip root folder in building inventory path. + if entity.Parent == nil { + continue + } + val = path.Join(val, entity.Name) + } + + return val +} + +func HostSystemManagementIPs(config []types.VirtualNicManagerNetConfig) []net.IP { + var ips []net.IP + + for _, nc := range config { + if nc.NicType != string(types.HostVirtualNicManagerNicTypeManagement) { + continue + } + for ix := range nc.CandidateVnic { + for _, selectedVnicKey := range nc.SelectedVnic { + if nc.CandidateVnic[ix].Key != selectedVnicKey { + continue + } + ip := net.ParseIP(nc.CandidateVnic[ix].Spec.Ip.IpAddress) + if ip != nil { + ips = append(ips, ip) + } + } + } + } + + return ips +} + +// UsingEnvoySidecar determines if the given *vim25.Client is using vCenter's +// local Envoy sidecar (as opposed to using the HTTPS port.) +// Returns a boolean indicating whether to use the sidecar or not. +func UsingEnvoySidecar(c *vim25.Client) bool { + envoySidecarPort := os.Getenv("GOVMOMI_ENVOY_SIDECAR_PORT") + if envoySidecarPort == "" { + envoySidecarPort = "1080" + } + envoySidecarHost := os.Getenv("GOVMOMI_ENVOY_SIDECAR_HOST") + if envoySidecarHost == "" { + envoySidecarHost = "localhost" + } + return c.URL().Hostname() == envoySidecarHost && c.URL().Scheme == "http" && c.URL().Port() == envoySidecarPort +} + +// ClientWithEnvoyHostGateway clones the provided soap.Client and returns a new +// one that uses a Unix socket to leverage vCenter's local Envoy host +// gateway. +// This should be used to construct clients that talk to ESX. +// This method returns a new *vim25.Client and does not modify the original input. +// This client disables HTTP keep alives and is intended for a single round +// trip. (eg. guest file transfer, datastore file transfer) +func ClientWithEnvoyHostGateway(vc *vim25.Client) *vim25.Client { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + sc := soap.NewClient(vc.URL(), true) + // Clone the underlying HTTP transport, only replacing the dialer logic. + transport := sc.DefaultTransport().Clone() + hostGatewaySocketPath := os.Getenv(vCenterHostGatewaySocketEnv) + if hostGatewaySocketPath == "" { + hostGatewaySocketPath = vCenterHostGatewaySocket + } + transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", hostGatewaySocketPath) + } + // We use this client for a single request, so we don't require keepalives. + transport.DisableKeepAlives = true + sc.Client = http.Client{ + Transport: transport, + } + newVC := &vim25.Client{ + Client: sc, + } + return newVC +} + +// HostGatewayTransferURL rewrites the provided URL to be suitable for use +// with the Envoy host gateway on vCenter. +// It returns a copy of the provided URL with the host, scheme rewritten as needed. +// Receivers of such URLs must typically also use ClientWithEnvoyHostGateway to +// use the appropriate http.Transport to be able to make use of the host +// gateway. +// nil input yields an uninitialized struct. +func HostGatewayTransferURL(u *url.URL, hostMoref types.ManagedObjectReference) *url.URL { + if u == nil { + return &url.URL{} + } + // Make a copy of the provided URL. + turl := *u + turl.Host = "localhost" + turl.Scheme = "http" + oldPath := turl.Path + turl.Path = fmt.Sprintf("/hgw/%s%s", hostMoref.Value, oldPath) + return &turl +} diff --git a/vendor/github.com/vmware/govmomi/internal/methods.go b/vendor/github.com/vmware/govmomi/internal/methods.go new file mode 100644 index 0000000000..95ccee8d24 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/internal/methods.go @@ -0,0 +1,123 @@ +/* +Copyright (c) 2014-2015 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 internal + +import ( + "context" + + "github.com/vmware/govmomi/vim25/soap" +) + +type RetrieveDynamicTypeManagerBody struct { + Req *RetrieveDynamicTypeManagerRequest `xml:"urn:vim25 RetrieveDynamicTypeManager"` + Res *RetrieveDynamicTypeManagerResponse `xml:"urn:vim25 RetrieveDynamicTypeManagerResponse"` + Fault_ *soap.Fault +} + +func (b *RetrieveDynamicTypeManagerBody) Fault() *soap.Fault { return b.Fault_ } + +func RetrieveDynamicTypeManager(ctx context.Context, r soap.RoundTripper, req *RetrieveDynamicTypeManagerRequest) (*RetrieveDynamicTypeManagerResponse, error) { + var reqBody, resBody RetrieveDynamicTypeManagerBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type RetrieveManagedMethodExecuterBody struct { + Req *RetrieveManagedMethodExecuterRequest `xml:"urn:vim25 RetrieveManagedMethodExecuter"` + Res *RetrieveManagedMethodExecuterResponse `xml:"urn:vim25 RetrieveManagedMethodExecuterResponse"` + Fault_ *soap.Fault +} + +func (b *RetrieveManagedMethodExecuterBody) Fault() *soap.Fault { return b.Fault_ } + +func RetrieveManagedMethodExecuter(ctx context.Context, r soap.RoundTripper, req *RetrieveManagedMethodExecuterRequest) (*RetrieveManagedMethodExecuterResponse, error) { + var reqBody, resBody RetrieveManagedMethodExecuterBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type DynamicTypeMgrQueryMoInstancesBody struct { + Req *DynamicTypeMgrQueryMoInstancesRequest `xml:"urn:vim25 DynamicTypeMgrQueryMoInstances"` + Res *DynamicTypeMgrQueryMoInstancesResponse `xml:"urn:vim25 DynamicTypeMgrQueryMoInstancesResponse"` + Fault_ *soap.Fault +} + +func (b *DynamicTypeMgrQueryMoInstancesBody) Fault() *soap.Fault { return b.Fault_ } + +func DynamicTypeMgrQueryMoInstances(ctx context.Context, r soap.RoundTripper, req *DynamicTypeMgrQueryMoInstancesRequest) (*DynamicTypeMgrQueryMoInstancesResponse, error) { + var reqBody, resBody DynamicTypeMgrQueryMoInstancesBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type DynamicTypeMgrQueryTypeInfoBody struct { + Req *DynamicTypeMgrQueryTypeInfoRequest `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfo"` + Res *DynamicTypeMgrQueryTypeInfoResponse `xml:"urn:vim25 DynamicTypeMgrQueryTypeInfoResponse"` + Fault_ *soap.Fault +} + +func (b *DynamicTypeMgrQueryTypeInfoBody) Fault() *soap.Fault { return b.Fault_ } + +func DynamicTypeMgrQueryTypeInfo(ctx context.Context, r soap.RoundTripper, req *DynamicTypeMgrQueryTypeInfoRequest) (*DynamicTypeMgrQueryTypeInfoResponse, error) { + var reqBody, resBody DynamicTypeMgrQueryTypeInfoBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type ExecuteSoapBody struct { + Req *ExecuteSoapRequest `xml:"urn:vim25 ExecuteSoap"` + Res *ExecuteSoapResponse `xml:"urn:vim25 ExecuteSoapResponse"` + Fault_ *soap.Fault +} + +func (b *ExecuteSoapBody) Fault() *soap.Fault { return b.Fault_ } + +func ExecuteSoap(ctx context.Context, r soap.RoundTripper, req *ExecuteSoapRequest) (*ExecuteSoapResponse, error) { + var reqBody, resBody ExecuteSoapBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} diff --git a/vendor/github.com/vmware/govmomi/internal/types.go b/vendor/github.com/vmware/govmomi/internal/types.go new file mode 100644 index 0000000000..b84103b89b --- /dev/null +++ b/vendor/github.com/vmware/govmomi/internal/types.go @@ -0,0 +1,270 @@ +/* +Copyright (c) 2014 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 internal + +import ( + "reflect" + + "github.com/vmware/govmomi/vim25/types" +) + +type DynamicTypeMgrQueryMoInstancesRequest struct { + This types.ManagedObjectReference `xml:"_this"` + FilterSpec BaseDynamicTypeMgrFilterSpec `xml:"filterSpec,omitempty,typeattr"` +} + +type DynamicTypeMgrQueryMoInstancesResponse struct { + Returnval []DynamicTypeMgrMoInstance `xml:"urn:vim25 returnval"` +} + +type DynamicTypeEnumTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + WsdlName string `xml:"wsdlName"` + Version string `xml:"version"` + Value []string `xml:"value,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +func init() { + types.Add("DynamicTypeEnumTypeInfo", reflect.TypeOf((*DynamicTypeEnumTypeInfo)(nil)).Elem()) +} + +type DynamicTypeMgrAllTypeInfoRequest struct { + types.DynamicData + + ManagedTypeInfo []DynamicTypeMgrManagedTypeInfo `xml:"managedTypeInfo,omitempty"` + EnumTypeInfo []DynamicTypeEnumTypeInfo `xml:"enumTypeInfo,omitempty"` + DataTypeInfo []DynamicTypeMgrDataTypeInfo `xml:"dataTypeInfo,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrAllTypeInfo", reflect.TypeOf((*DynamicTypeMgrAllTypeInfoRequest)(nil)).Elem()) +} + +type DynamicTypeMgrAnnotation struct { + types.DynamicData + + Name string `xml:"name"` + Parameter []string `xml:"parameter,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrAnnotation", reflect.TypeOf((*DynamicTypeMgrAnnotation)(nil)).Elem()) +} + +type DynamicTypeMgrDataTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + WsdlName string `xml:"wsdlName"` + Version string `xml:"version"` + Base []string `xml:"base,omitempty"` + Property []DynamicTypeMgrPropertyTypeInfo `xml:"property,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrDataTypeInfo", reflect.TypeOf((*DynamicTypeMgrDataTypeInfo)(nil)).Elem()) +} + +func (b *DynamicTypeMgrFilterSpec) GetDynamicTypeMgrFilterSpec() *DynamicTypeMgrFilterSpec { return b } + +type BaseDynamicTypeMgrFilterSpec interface { + GetDynamicTypeMgrFilterSpec() *DynamicTypeMgrFilterSpec +} + +type DynamicTypeMgrFilterSpec struct { + types.DynamicData +} + +func init() { + types.Add("DynamicTypeMgrFilterSpec", reflect.TypeOf((*DynamicTypeMgrFilterSpec)(nil)).Elem()) +} + +type DynamicTypeMgrManagedTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + WsdlName string `xml:"wsdlName"` + Version string `xml:"version"` + Base []string `xml:"base,omitempty"` + Property []DynamicTypeMgrPropertyTypeInfo `xml:"property,omitempty"` + Method []DynamicTypeMgrMethodTypeInfo `xml:"method,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrManagedTypeInfo", reflect.TypeOf((*DynamicTypeMgrManagedTypeInfo)(nil)).Elem()) +} + +type DynamicTypeMgrMethodTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + WsdlName string `xml:"wsdlName"` + Version string `xml:"version"` + ParamTypeInfo []DynamicTypeMgrParamTypeInfo `xml:"paramTypeInfo,omitempty"` + ReturnTypeInfo *DynamicTypeMgrParamTypeInfo `xml:"returnTypeInfo,omitempty"` + Fault []string `xml:"fault,omitempty"` + PrivId string `xml:"privId,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrMethodTypeInfo", reflect.TypeOf((*DynamicTypeMgrMethodTypeInfo)(nil)).Elem()) +} + +type DynamicTypeMgrMoFilterSpec struct { + DynamicTypeMgrFilterSpec + + Id string `xml:"id,omitempty"` + TypeSubstr string `xml:"typeSubstr,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrMoFilterSpec", reflect.TypeOf((*DynamicTypeMgrMoFilterSpec)(nil)).Elem()) +} + +type DynamicTypeMgrMoInstance struct { + types.DynamicData + + Id string `xml:"id"` + MoType string `xml:"moType"` +} + +func init() { + types.Add("DynamicTypeMgrMoInstance", reflect.TypeOf((*DynamicTypeMgrMoInstance)(nil)).Elem()) +} + +type DynamicTypeMgrParamTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + Version string `xml:"version"` + Type string `xml:"type"` + PrivId string `xml:"privId,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrParamTypeInfo", reflect.TypeOf((*DynamicTypeMgrParamTypeInfo)(nil)).Elem()) +} + +type DynamicTypeMgrPropertyTypeInfo struct { + types.DynamicData + + Name string `xml:"name"` + Version string `xml:"version"` + Type string `xml:"type"` + PrivId string `xml:"privId,omitempty"` + MsgIdFormat string `xml:"msgIdFormat,omitempty"` + Annotation []DynamicTypeMgrAnnotation `xml:"annotation,omitempty"` +} + +type DynamicTypeMgrQueryTypeInfoRequest struct { + This types.ManagedObjectReference `xml:"_this"` + FilterSpec BaseDynamicTypeMgrFilterSpec `xml:"filterSpec,omitempty,typeattr"` +} + +type DynamicTypeMgrQueryTypeInfoResponse struct { + Returnval DynamicTypeMgrAllTypeInfoRequest `xml:"urn:vim25 returnval"` +} + +func init() { + types.Add("DynamicTypeMgrPropertyTypeInfo", reflect.TypeOf((*DynamicTypeMgrPropertyTypeInfo)(nil)).Elem()) +} + +type DynamicTypeMgrTypeFilterSpec struct { + DynamicTypeMgrFilterSpec + + TypeSubstr string `xml:"typeSubstr,omitempty"` +} + +func init() { + types.Add("DynamicTypeMgrTypeFilterSpec", reflect.TypeOf((*DynamicTypeMgrTypeFilterSpec)(nil)).Elem()) +} + +type ReflectManagedMethodExecuterSoapArgument struct { + types.DynamicData + + Name string `xml:"name"` + Val string `xml:"val"` +} + +func init() { + types.Add("ReflectManagedMethodExecuterSoapArgument", reflect.TypeOf((*ReflectManagedMethodExecuterSoapArgument)(nil)).Elem()) +} + +type ReflectManagedMethodExecuterSoapFault struct { + types.DynamicData + + FaultMsg string `xml:"faultMsg"` + FaultDetail string `xml:"faultDetail,omitempty"` +} + +func init() { + types.Add("ReflectManagedMethodExecuterSoapFault", reflect.TypeOf((*ReflectManagedMethodExecuterSoapFault)(nil)).Elem()) +} + +type ReflectManagedMethodExecuterSoapResult struct { + types.DynamicData + + Response string `xml:"response,omitempty"` + Fault *ReflectManagedMethodExecuterSoapFault `xml:"fault,omitempty"` +} + +type RetrieveDynamicTypeManagerRequest struct { + This types.ManagedObjectReference `xml:"_this"` +} + +type RetrieveDynamicTypeManagerResponse struct { + Returnval *InternalDynamicTypeManager `xml:"urn:vim25 returnval"` +} + +type RetrieveManagedMethodExecuterRequest struct { + This types.ManagedObjectReference `xml:"_this"` +} + +func init() { + types.Add("RetrieveManagedMethodExecuter", reflect.TypeOf((*RetrieveManagedMethodExecuterRequest)(nil)).Elem()) +} + +type RetrieveManagedMethodExecuterResponse struct { + Returnval *ReflectManagedMethodExecuter `xml:"urn:vim25 returnval"` +} + +type InternalDynamicTypeManager struct { + types.ManagedObjectReference +} + +type ReflectManagedMethodExecuter struct { + types.ManagedObjectReference +} + +type ExecuteSoapRequest struct { + This types.ManagedObjectReference `xml:"_this"` + Moid string `xml:"moid"` + Version string `xml:"version"` + Method string `xml:"method"` + Argument []ReflectManagedMethodExecuterSoapArgument `xml:"argument,omitempty"` +} + +type ExecuteSoapResponse struct { + Returnval *ReflectManagedMethodExecuterSoapResult `xml:"urn:vim25 returnval"` +} diff --git a/vendor/github.com/vmware/govmomi/internal/version/version.go b/vendor/github.com/vmware/govmomi/internal/version/version.go new file mode 100644 index 0000000000..02c62ece52 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/internal/version/version.go @@ -0,0 +1,25 @@ +/* +Copyright (c) 2014-2022 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 version + +const ( + // ClientName is the name of this SDK + ClientName = "govmomi" + + // ClientVersion is the version of this SDK + ClientVersion = "0.37.1" +) diff --git a/vendor/github.com/vmware/govmomi/nfc/lease.go b/vendor/github.com/vmware/govmomi/nfc/lease.go index 3fb85ee6f6..eb3ef9fcaf 100644 --- a/vendor/github.com/vmware/govmomi/nfc/lease.go +++ b/vendor/github.com/vmware/govmomi/nfc/lease.go @@ -18,16 +18,15 @@ package nfc import ( "context" - "errors" "fmt" "io" "path" "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/task" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" - "github.com/vmware/govmomi/vim25/progress" "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" ) @@ -72,17 +71,17 @@ func (l *Lease) Complete(ctx context.Context) error { } // GetManifest wraps methods.GetManifest -func (l *Lease) GetManifest(ctx context.Context) error { +func (l *Lease) GetManifest(ctx context.Context) ([]types.HttpNfcLeaseManifestEntry, error) { req := types.HttpNfcLeaseGetManifest{ This: l.Reference(), } - _, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req) + res, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req) if err != nil { - return err + return nil, err } - return nil + return res.Returnval, nil } // Progress wraps methods.Progress @@ -195,7 +194,7 @@ func (l *Lease) Wait(ctx context.Context, items []types.OvfFileItem) (*LeaseInfo } if lease.Error != nil { - return nil, errors.New(lease.Error.LocalizedMessage) + return nil, &task.Error{LocalizedMethodFault: lease.Error} } return nil, fmt.Errorf("unexpected nfc lease state: %s", lease.State) @@ -208,8 +207,6 @@ func (l *Lease) StartUpdater(ctx context.Context, info *LeaseInfo) *LeaseUpdater func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soap.Upload) error { if opts.Progress == nil { opts.Progress = item - } else { - opts.Progress = progress.Tee(item, opts.Progress) } // Non-disk files (such as .iso) use the PUT method. @@ -230,8 +227,6 @@ func (l *Lease) Upload(ctx context.Context, item FileItem, f io.Reader, opts soa func (l *Lease) DownloadFile(ctx context.Context, file string, item FileItem, opts soap.Download) error { if opts.Progress == nil { opts.Progress = item - } else { - opts.Progress = progress.Tee(item, opts.Progress) } return l.c.DownloadFile(ctx, file, item.URL, &opts) diff --git a/vendor/github.com/vmware/govmomi/nfc/lease_updater.go b/vendor/github.com/vmware/govmomi/nfc/lease_updater.go index d77c3596ae..02ce9cf537 100644 --- a/vendor/github.com/vmware/govmomi/nfc/lease_updater.go +++ b/vendor/github.com/vmware/govmomi/nfc/lease_updater.go @@ -57,8 +57,8 @@ func (o FileItem) File() types.OvfFile { } type LeaseUpdater struct { - pos int64 // Number of bytes (keep first to ensure 64 bit aligment) - total int64 // Total number of bytes (keep first to ensure 64 bit aligment) + pos int64 // Number of bytes (keep first to ensure 64 bit alignment) + total int64 // Total number of bytes (keep first to ensure 64 bit alignment) lease *Lease diff --git a/vendor/github.com/vmware/govmomi/object/authorization_manager.go b/vendor/github.com/vmware/govmomi/object/authorization_manager.go index b703258fe7..5cd6851a87 100644 --- a/vendor/github.com/vmware/govmomi/object/authorization_manager.go +++ b/vendor/github.com/vmware/govmomi/object/authorization_manager.go @@ -172,3 +172,50 @@ func (m AuthorizationManager) UpdateRole(ctx context.Context, id int32, name str _, err := methods.UpdateAuthorizationRole(ctx, m.Client(), &req) return err } + +func (m AuthorizationManager) HasUserPrivilegeOnEntities(ctx context.Context, entities []types.ManagedObjectReference, userName string, privID []string) ([]types.EntityPrivilege, error) { + req := types.HasUserPrivilegeOnEntities{ + This: m.Reference(), + Entities: entities, + UserName: userName, + PrivId: privID, + } + + res, err := methods.HasUserPrivilegeOnEntities(ctx, m.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (m AuthorizationManager) HasPrivilegeOnEntity(ctx context.Context, entity types.ManagedObjectReference, sessionID string, privID []string) ([]bool, error) { + req := types.HasPrivilegeOnEntity{ + This: m.Reference(), + Entity: entity, + SessionId: sessionID, + PrivId: privID, + } + + res, err := methods.HasPrivilegeOnEntity(ctx, m.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (m AuthorizationManager) FetchUserPrivilegeOnEntities(ctx context.Context, entities []types.ManagedObjectReference, userName string) ([]types.UserPrivilegeResult, error) { + req := types.FetchUserPrivilegeOnEntities{ + This: m.Reference(), + Entities: entities, + UserName: userName, + } + + res, err := methods.FetchUserPrivilegeOnEntities(ctx, m.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/cluster_compute_resource.go b/vendor/github.com/vmware/govmomi/object/cluster_compute_resource.go index 24c346825a..018372dfe0 100644 --- a/vendor/github.com/vmware/govmomi/object/cluster_compute_resource.go +++ b/vendor/github.com/vmware/govmomi/object/cluster_compute_resource.go @@ -87,3 +87,17 @@ func (c ClusterComputeResource) MoveInto(ctx context.Context, hosts ...*HostSyst return NewTask(c.c, res.Returnval), nil } + +func (c ClusterComputeResource) PlaceVm(ctx context.Context, spec types.PlacementSpec) (*types.PlacementResult, error) { + req := types.PlaceVm{ + This: c.Reference(), + PlacementSpec: spec, + } + + res, err := methods.PlaceVm(ctx, c.c, &req) + if err != nil { + return nil, err + } + + return &res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/common.go b/vendor/github.com/vmware/govmomi/object/common.go index abb4076c7f..88ce78fce5 100644 --- a/vendor/github.com/vmware/govmomi/object/common.go +++ b/vendor/github.com/vmware/govmomi/object/common.go @@ -75,29 +75,22 @@ func (c *Common) SetInventoryPath(p string) { c.InventoryPath = p } -// ObjectName returns the base name of the InventoryPath field if set, -// otherwise fetches the mo.ManagedEntity.Name field via the property collector. +// ObjectName fetches the mo.ManagedEntity.Name field via the property collector. func (c Common) ObjectName(ctx context.Context) (string, error) { - var o mo.ManagedEntity + var content []types.ObjectContent - err := c.Properties(ctx, c.Reference(), []string{"name"}, &o) + err := c.Properties(ctx, c.Reference(), []string{"name"}, &content) if err != nil { return "", err } - if o.Name != "" { - return o.Name, nil + for i := range content { + for _, prop := range content[i].PropSet { + return prop.Val.(string), nil + } } - // Network has its own "name" field... - var n mo.Network - - err = c.Properties(ctx, c.Reference(), []string{"name"}, &n) - if err != nil { - return "", err - } - - return n.Name, nil + return "", nil } // Properties is a wrapper for property.DefaultCollector().RetrieveOne() @@ -142,3 +135,14 @@ func (c Common) SetCustomValue(ctx context.Context, key string, value string) er _, err := methods.SetCustomValue(ctx, c.c, &req) return err } + +func ReferenceFromString(s string) *types.ManagedObjectReference { + var ref types.ManagedObjectReference + if !ref.FromString(s) { + return nil + } + if mo.IsManagedObjectType(ref.Type) { + return &ref + } + return nil +} diff --git a/vendor/github.com/vmware/govmomi/object/compute_resource.go b/vendor/github.com/vmware/govmomi/object/compute_resource.go index 7645fddaf3..4a2db74117 100644 --- a/vendor/github.com/vmware/govmomi/object/compute_resource.go +++ b/vendor/github.com/vmware/govmomi/object/compute_resource.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 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 +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, @@ -18,6 +18,7 @@ package object import ( "context" + "fmt" "path" "github.com/vmware/govmomi/property" @@ -84,6 +85,21 @@ func (c ComputeResource) Datastores(ctx context.Context) ([]*Datastore, error) { return dss, nil } +func (c ComputeResource) EnvironmentBrowser(ctx context.Context) (*EnvironmentBrowser, error) { + var cr mo.ComputeResource + + err := c.Properties(ctx, c.Reference(), []string{"environmentBrowser"}, &cr) + if err != nil { + return nil, err + } + + if cr.EnvironmentBrowser == nil { + return nil, fmt.Errorf("%s: nil environmentBrowser", c.Reference()) + } + + return NewEnvironmentBrowser(c.c, *cr.EnvironmentBrowser), nil +} + func (c ComputeResource) ResourcePool(ctx context.Context) (*ResourcePool, error) { var cr mo.ComputeResource diff --git a/vendor/github.com/vmware/govmomi/object/customization_spec_manager.go b/vendor/github.com/vmware/govmomi/object/customization_spec_manager.go index cb8b965dc6..e9a3914d9d 100644 --- a/vendor/github.com/vmware/govmomi/object/customization_spec_manager.go +++ b/vendor/github.com/vmware/govmomi/object/customization_spec_manager.go @@ -21,6 +21,7 @@ import ( "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -36,6 +37,12 @@ func NewCustomizationSpecManager(c *vim25.Client) *CustomizationSpecManager { return &cs } +func (cs CustomizationSpecManager) Info(ctx context.Context) ([]types.CustomizationSpecInfo, error) { + var m mo.CustomizationSpecManager + err := cs.Properties(ctx, cs.Reference(), []string{"info"}, &m) + return m.Info, err +} + func (cs CustomizationSpecManager) DoesCustomizationSpecExist(ctx context.Context, name string) (bool, error) { req := types.DoesCustomizationSpecExist{ This: cs.Reference(), diff --git a/vendor/github.com/vmware/govmomi/object/datastore.go b/vendor/github.com/vmware/govmomi/object/datastore.go index 46a99950a6..991ad4f822 100644 --- a/vendor/github.com/vmware/govmomi/object/datastore.go +++ b/vendor/github.com/vmware/govmomi/object/datastore.go @@ -27,6 +27,7 @@ import ( "path" "strings" + "github.com/vmware/govmomi/internal" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/session" "github.com/vmware/govmomi/vim25" @@ -67,7 +68,37 @@ func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore } } +// FindInventoryPath sets InventoryPath and DatacenterPath, +// needed by NewURL() to compose an upload/download endpoint URL +func (d *Datastore) FindInventoryPath(ctx context.Context) error { + entities, err := mo.Ancestors(ctx, d.c, d.c.ServiceContent.PropertyCollector, d.r) + if err != nil { + return err + } + + val := "/" + + for _, entity := range entities { + if entity.Parent == nil { + continue // root folder + } + val = path.Join(val, entity.Name) + if entity.Self.Type == "Datacenter" { + d.DatacenterPath = val + } + } + + d.InventoryPath = val + + return nil +} + func (d Datastore) Path(path string) string { + var p DatastorePath + if p.FromString(path) { + return p.String() // already in "[datastore] path" format + } + return (&DatastorePath{ Datastore: d.Name(), Path: path, @@ -78,8 +109,14 @@ func (d Datastore) Path(path string) string { func (d Datastore) NewURL(path string) *url.URL { u := d.c.URL() + scheme := u.Scheme + // In rare cases where vCenter and ESX are accessed using different schemes. + if overrideScheme := os.Getenv("GOVMOMI_DATASTORE_ACCESS_SCHEME"); overrideScheme != "" { + scheme = overrideScheme + } + return &url.URL{ - Scheme: u.Scheme, + Scheme: scheme, Host: u.Host, Path: fmt.Sprintf("/folder/%s", path), RawQuery: url.Values{ @@ -89,11 +126,6 @@ func (d Datastore) NewURL(path string) *url.URL { } } -// URL is deprecated, use NewURL instead. -func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) { - return d.NewURL(path), nil -} - func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) { var do mo.Datastore @@ -174,6 +206,10 @@ func (d Datastore) HostContext(ctx context.Context, host *HostSystem) context.Co // that can be used along with the ticket cookie to access the given path. An host is chosen at random unless the // the given Context was created with a specific host via the HostContext method. func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) { + if d.InventoryPath == "" { + _ = d.FindInventoryPath(ctx) + } + u := d.NewURL(path) host, ok := ctx.Value(datastoreServiceTicketHostKey{}).(*HostSystem) @@ -218,8 +254,18 @@ func (d Datastore) ServiceTicket(ctx context.Context, path string, method string delete(q, "dcPath") u.RawQuery = q.Encode() + // Now that we have a host selected, take a copy of the URL. + transferURL := *u + + if internal.UsingEnvoySidecar(d.Client()) { + // Rewrite the host URL to go through the Envoy sidecar on VC. + // Reciever must use a custom dialer. + u = internal.HostGatewayTransferURL(u, host.Reference()) + } + spec := types.SessionManagerHttpServiceRequestSpec{ - Url: u.String(), + // Use the original URL (without rewrites) for the session ticket. + Url: transferURL.String(), // See SessionManagerHttpServiceRequestSpecMethod enum Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])), } @@ -256,7 +302,10 @@ func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Up return nil, nil, err } - p.Ticket = ticket + if ticket != nil { + p.Ticket = ticket + p.Close = true // disable Keep-Alive connection to ESX + } return u, &p, nil } @@ -272,7 +321,10 @@ func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap. return nil, nil, err } - p.Ticket = ticket + if ticket != nil { + p.Ticket = ticket + p.Close = true // disable Keep-Alive connection to ESX + } return u, &p, nil } @@ -292,7 +344,13 @@ func (d Datastore) UploadFile(ctx context.Context, file string, path string, par if err != nil { return err } - return d.Client().UploadFile(ctx, file, u, p) + vc := d.Client() + if internal.UsingEnvoySidecar(vc) { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + vc = internal.ClientWithEnvoyHostGateway(vc) + } + return vc.UploadFile(ctx, file, u, p) } // Download via soap.Download with an http service ticket @@ -310,7 +368,13 @@ func (d Datastore) DownloadFile(ctx context.Context, path string, file string, p if err != nil { return err } - return d.Client().DownloadFile(ctx, file, u, p) + vc := d.Client() + if internal.UsingEnvoySidecar(vc) { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + vc = internal.ClientWithEnvoyHostGateway(vc) + } + return vc.DownloadFile(ctx, file, u, p) } // AttachedHosts returns hosts that have this Datastore attached, accessible and writable. diff --git a/vendor/github.com/vmware/govmomi/object/datastore_file.go b/vendor/github.com/vmware/govmomi/object/datastore_file.go index bc010fc36e..86d7d9c728 100644 --- a/vendor/github.com/vmware/govmomi/object/datastore_file.go +++ b/vendor/github.com/vmware/govmomi/object/datastore_file.go @@ -297,10 +297,8 @@ func (f *DatastoreFile) TailFunc(lines int, include func(line int, message strin nread = bsize + remain eof = true - } else { - if pos, err = f.Seek(offset, io.SeekEnd); err != nil { - return err - } + } else if pos, err = f.Seek(offset, io.SeekEnd); err != nil { + return err } if _, err = io.CopyN(buf, f, nread); err != nil { diff --git a/vendor/github.com/vmware/govmomi/object/datastore_path.go b/vendor/github.com/vmware/govmomi/object/datastore_path.go index 1563ee1e11..104c7dfe35 100644 --- a/vendor/github.com/vmware/govmomi/object/datastore_path.go +++ b/vendor/github.com/vmware/govmomi/object/datastore_path.go @@ -31,7 +31,7 @@ type DatastorePath struct { // FromString parses a datastore path. // Returns true if the path could be parsed, false otherwise. func (p *DatastorePath) FromString(s string) bool { - if len(s) == 0 { + if s == "" { return false } diff --git a/vendor/github.com/vmware/govmomi/object/diagnostic_manager.go b/vendor/github.com/vmware/govmomi/object/diagnostic_manager.go index 5baf1ad903..026dc1cb5e 100644 --- a/vendor/github.com/vmware/govmomi/object/diagnostic_manager.go +++ b/vendor/github.com/vmware/govmomi/object/diagnostic_manager.go @@ -71,10 +71,8 @@ func (m DiagnosticManager) GenerateLogBundles(ctx context.Context, includeDefaul IncludeDefault: includeDefault, } - if host != nil { - for _, h := range host { - req.Host = append(req.Host, h.Reference()) - } + for _, h := range host { + req.Host = append(req.Host, h.Reference()) } res, err := methods.GenerateLogBundles_Task(ctx, m.c, &req) diff --git a/vendor/github.com/vmware/govmomi/object/distributed_virtual_portgroup.go b/vendor/github.com/vmware/govmomi/object/distributed_virtual_portgroup.go index f8ac5512c1..c2abb8fabd 100644 --- a/vendor/github.com/vmware/govmomi/object/distributed_virtual_portgroup.go +++ b/vendor/github.com/vmware/govmomi/object/distributed_virtual_portgroup.go @@ -36,6 +36,10 @@ func NewDistributedVirtualPortgroup(c *vim25.Client, ref types.ManagedObjectRefe } } +func (p DistributedVirtualPortgroup) GetInventoryPath() string { + return p.InventoryPath +} + // EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this DistributedVirtualPortgroup func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) { var dvp mo.DistributedVirtualPortgroup @@ -46,9 +50,15 @@ func (p DistributedVirtualPortgroup) EthernetCardBackingInfo(ctx context.Context return nil, err } + // From the docs at https://code.vmware.com/apis/196/vsphere/doc/vim.dvs.DistributedVirtualPortgroup.ConfigInfo.html: // "This property should always be set unless the user's setting does not have System.Read privilege on the object referred to by this property." + // Note that "the object" refers to the Switch, not the PortGroup. if dvp.Config.DistributedVirtualSwitch == nil { - return nil, fmt.Errorf("no System.Read privilege on: %s.%s", p.Reference(), prop) + name := p.InventoryPath + if name == "" { + name = p.Reference().String() + } + return nil, fmt.Errorf("failed to create EthernetCardBackingInfo for %s: System.Read privilege required for %s", name, prop) } if err := p.Properties(ctx, *dvp.Config.DistributedVirtualSwitch, []string{"uuid"}, &dvs); err != nil { diff --git a/vendor/github.com/vmware/govmomi/object/distributed_virtual_switch.go b/vendor/github.com/vmware/govmomi/object/distributed_virtual_switch.go index 526ce4bf78..66650e1d06 100644 --- a/vendor/github.com/vmware/govmomi/object/distributed_virtual_switch.go +++ b/vendor/github.com/vmware/govmomi/object/distributed_virtual_switch.go @@ -18,6 +18,7 @@ package object import ( "context" + "fmt" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" @@ -34,8 +35,17 @@ func NewDistributedVirtualSwitch(c *vim25.Client, ref types.ManagedObjectReferen } } +func (s DistributedVirtualSwitch) GetInventoryPath() string { + return s.InventoryPath +} + func (s DistributedVirtualSwitch) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) { - return nil, ErrNotSupported // TODO: just to satisfy NetworkReference interface for the finder + ref := s.Reference() + name := s.InventoryPath + if name == "" { + name = ref.String() + } + return nil, fmt.Errorf("type %s (%s) cannot be used for EthernetCardBackingInfo", ref.Type, name) } func (s DistributedVirtualSwitch) Reconfigure(ctx context.Context, spec types.BaseDVSConfigSpec) (*Task, error) { @@ -78,3 +88,31 @@ func (s DistributedVirtualSwitch) FetchDVPorts(ctx context.Context, criteria *ty } return res.Returnval, nil } + +func (s DistributedVirtualSwitch) ReconfigureDVPort(ctx context.Context, spec []types.DVPortConfigSpec) (*Task, error) { + req := types.ReconfigureDVPort_Task{ + This: s.Reference(), + Port: spec, + } + + res, err := methods.ReconfigureDVPort_Task(ctx, s.Client(), &req) + if err != nil { + return nil, err + } + + return NewTask(s.Client(), res.Returnval), nil +} + +func (s DistributedVirtualSwitch) ReconfigureLACP(ctx context.Context, spec []types.VMwareDvsLacpGroupSpec) (*Task, error) { + req := types.UpdateDVSLacpGroupConfig_Task{ + This: s.Reference(), + LacpGroupSpec: spec, + } + + res, err := methods.UpdateDVSLacpGroupConfig_Task(ctx, s.Client(), &req) + if err != nil { + return nil, err + } + + return NewTask(s.Client(), res.Returnval), nil +} diff --git a/vendor/github.com/vmware/govmomi/object/environment_browser.go b/vendor/github.com/vmware/govmomi/object/environment_browser.go new file mode 100644 index 0000000000..54ab4cb8d5 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/object/environment_browser.go @@ -0,0 +1,98 @@ +/* +Copyright (c) 2023-2023 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 object + +import ( + "context" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +type EnvironmentBrowser struct { + Common +} + +func NewEnvironmentBrowser(c *vim25.Client, ref types.ManagedObjectReference) *EnvironmentBrowser { + return &EnvironmentBrowser{ + Common: NewCommon(c, ref), + } +} + +func (b EnvironmentBrowser) QueryConfigTarget(ctx context.Context, host *HostSystem) (*types.ConfigTarget, error) { + req := types.QueryConfigTarget{ + This: b.Reference(), + } + + if host != nil { + ref := host.Reference() + req.Host = &ref + } + + res, err := methods.QueryConfigTarget(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryTargetCapabilities(ctx context.Context, host *HostSystem) (*types.HostCapability, error) { + req := types.QueryTargetCapabilities{ + This: b.Reference(), + } + + if host != nil { + ref := host.Reference() + req.Host = &ref + } + + res, err := methods.QueryTargetCapabilities(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryConfigOption(ctx context.Context, spec *types.EnvironmentBrowserConfigOptionQuerySpec) (*types.VirtualMachineConfigOption, error) { + req := types.QueryConfigOptionEx{ + This: b.Reference(), + Spec: spec, + } + + res, err := methods.QueryConfigOptionEx(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryConfigOptionDescriptor(ctx context.Context) ([]types.VirtualMachineConfigOptionDescriptor, error) { + req := types.QueryConfigOptionDescriptor{ + This: b.Reference(), + } + + res, err := methods.QueryConfigOptionDescriptor(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/folder.go b/vendor/github.com/vmware/govmomi/object/folder.go index 7a69949f95..6e0a7649b9 100644 --- a/vendor/github.com/vmware/govmomi/object/folder.go +++ b/vendor/github.com/vmware/govmomi/object/folder.go @@ -225,3 +225,17 @@ func (f Folder) MoveInto(ctx context.Context, list []types.ManagedObjectReferenc return NewTask(f.c, res.Returnval), nil } + +func (f Folder) PlaceVmsXCluster(ctx context.Context, spec types.PlaceVmsXClusterSpec) (*types.PlaceVmsXClusterResult, error) { + req := types.PlaceVmsXCluster{ + This: f.Reference(), + PlacementSpec: spec, + } + + res, err := methods.PlaceVmsXCluster(ctx, f.c, &req) + if err != nil { + return nil, err + } + + return &res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/history_collector.go b/vendor/github.com/vmware/govmomi/object/history_collector.go deleted file mode 100644 index afdcab78b6..0000000000 --- a/vendor/github.com/vmware/govmomi/object/history_collector.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright (c) 2015 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 object - -import ( - "context" - - "github.com/vmware/govmomi/vim25" - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" -) - -type HistoryCollector struct { - Common -} - -func NewHistoryCollector(c *vim25.Client, ref types.ManagedObjectReference) *HistoryCollector { - return &HistoryCollector{ - Common: NewCommon(c, ref), - } -} - -func (h HistoryCollector) Destroy(ctx context.Context) error { - req := types.DestroyCollector{ - This: h.Reference(), - } - - _, err := methods.DestroyCollector(ctx, h.c, &req) - return err -} - -func (h HistoryCollector) Reset(ctx context.Context) error { - req := types.ResetCollector{ - This: h.Reference(), - } - - _, err := methods.ResetCollector(ctx, h.c, &req) - return err -} - -func (h HistoryCollector) Rewind(ctx context.Context) error { - req := types.RewindCollector{ - This: h.Reference(), - } - - _, err := methods.RewindCollector(ctx, h.c, &req) - return err -} - -func (h HistoryCollector) SetPageSize(ctx context.Context, maxCount int32) error { - req := types.SetCollectorPageSize{ - This: h.Reference(), - MaxCount: maxCount, - } - - _, err := methods.SetCollectorPageSize(ctx, h.c, &req) - return err -} diff --git a/vendor/github.com/vmware/govmomi/object/host_certificate_info.go b/vendor/github.com/vmware/govmomi/object/host_certificate_info.go index 52c26a9dd6..1a3a7fab54 100644 --- a/vendor/github.com/vmware/govmomi/object/host_certificate_info.go +++ b/vendor/github.com/vmware/govmomi/object/host_certificate_info.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2016-2023 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 +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, @@ -17,7 +17,6 @@ limitations under the License. package object import ( - "crypto/sha256" "crypto/tls" "crypto/x509" "crypto/x509/pkix" @@ -36,10 +35,10 @@ import ( type HostCertificateInfo struct { types.HostCertificateManagerCertificateInfo - ThumbprintSHA1 string - ThumbprintSHA256 string + ThumbprintSHA1 string `json:"thumbprintSHA1"` + ThumbprintSHA256 string `json:"thumbprintSHA256"` - Err error + Err error `json:"err"` Certificate *x509.Certificate `json:"-"` subjectName *pkix.Name @@ -58,14 +57,7 @@ func (info *HostCertificateInfo) FromCertificate(cert *x509.Certificate) *HostCe info.Subject = info.fromName(info.subjectName) info.ThumbprintSHA1 = soap.ThumbprintSHA1(cert) - - // SHA-256 for info purposes only, API fields all use SHA-1 - sum := sha256.Sum256(cert.Raw) - hex := make([]string, len(sum)) - for i, b := range sum { - hex[i] = fmt.Sprintf("%02X", b) - } - info.ThumbprintSHA256 = strings.Join(hex, ":") + info.ThumbprintSHA256 = soap.ThumbprintSHA256(cert) if info.Status == "" { info.Status = string(types.HostCertificateManagerCertificateInfoCertificateStatusUnknown) @@ -86,10 +78,7 @@ func (info *HostCertificateInfo) FromURL(u *url.URL, config *tls.Config) error { conn, err := tls.Dial("tcp", addr, config) if err != nil { - switch err.(type) { - case x509.UnknownAuthorityError: - case x509.HostnameError: - default: + if !soap.IsCertificateUntrusted(err) { return err } diff --git a/vendor/github.com/vmware/govmomi/object/host_config_manager.go b/vendor/github.com/vmware/govmomi/object/host_config_manager.go index 123227ecc7..eac59a32eb 100644 --- a/vendor/github.com/vmware/govmomi/object/host_config_manager.go +++ b/vendor/github.com/vmware/govmomi/object/host_config_manager.go @@ -18,9 +18,9 @@ package object import ( "context" + "fmt" "github.com/vmware/govmomi/vim25" - "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -34,163 +34,138 @@ func NewHostConfigManager(c *vim25.Client, ref types.ManagedObjectReference) *Ho } } -func (m HostConfigManager) DatastoreSystem(ctx context.Context) (*HostDatastoreSystem, error) { - var h mo.HostSystem +// reference returns the ManagedObjectReference for the given HostConfigManager property name. +// An error is returned if the field is nil, of type ErrNotSupported if versioned is true. +func (m HostConfigManager) reference(ctx context.Context, name string, versioned ...bool) (types.ManagedObjectReference, error) { + prop := "configManager." + name + var content []types.ObjectContent - err := m.Properties(ctx, m.Reference(), []string{"configManager.datastoreSystem"}, &h) + err := m.Properties(ctx, m.Reference(), []string{prop}, &content) + if err != nil { + return types.ManagedObjectReference{}, err + } + + for _, c := range content { + for _, p := range c.PropSet { + if p.Name != prop { + continue + } + if ref, ok := p.Val.(types.ManagedObjectReference); ok { + return ref, nil + } + } + } + + err = fmt.Errorf("%s %s is nil", m.Reference(), prop) + if len(versioned) == 1 && versioned[0] { + err = ErrNotSupported + } + return types.ManagedObjectReference{}, err +} + +func (m HostConfigManager) DatastoreSystem(ctx context.Context) (*HostDatastoreSystem, error) { + ref, err := m.reference(ctx, "datastoreSystem") if err != nil { return nil, err } - - return NewHostDatastoreSystem(m.c, *h.ConfigManager.DatastoreSystem), nil + return NewHostDatastoreSystem(m.c, ref), nil } func (m HostConfigManager) NetworkSystem(ctx context.Context) (*HostNetworkSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.networkSystem"}, &h) + ref, err := m.reference(ctx, "networkSystem") if err != nil { return nil, err } - - return NewHostNetworkSystem(m.c, *h.ConfigManager.NetworkSystem), nil + return NewHostNetworkSystem(m.c, ref), nil } func (m HostConfigManager) FirewallSystem(ctx context.Context) (*HostFirewallSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.firewallSystem"}, &h) + ref, err := m.reference(ctx, "firewallSystem") if err != nil { return nil, err } - return NewHostFirewallSystem(m.c, *h.ConfigManager.FirewallSystem), nil + return NewHostFirewallSystem(m.c, ref), nil } func (m HostConfigManager) StorageSystem(ctx context.Context) (*HostStorageSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.storageSystem"}, &h) + ref, err := m.reference(ctx, "storageSystem") if err != nil { return nil, err } - - return NewHostStorageSystem(m.c, *h.ConfigManager.StorageSystem), nil + return NewHostStorageSystem(m.c, ref), nil } func (m HostConfigManager) VirtualNicManager(ctx context.Context) (*HostVirtualNicManager, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.virtualNicManager"}, &h) + ref, err := m.reference(ctx, "virtualNicManager") if err != nil { return nil, err } - - return NewHostVirtualNicManager(m.c, *h.ConfigManager.VirtualNicManager, m.Reference()), nil + return NewHostVirtualNicManager(m.c, ref, m.Reference()), nil } func (m HostConfigManager) VsanSystem(ctx context.Context) (*HostVsanSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanSystem"}, &h) + ref, err := m.reference(ctx, "vsanSystem", true) // Added in 5.5 if err != nil { return nil, err } - - // Added in 5.5 - if h.ConfigManager.VsanSystem == nil { - return nil, ErrNotSupported - } - - return NewHostVsanSystem(m.c, *h.ConfigManager.VsanSystem), nil + return NewHostVsanSystem(m.c, ref), nil } func (m HostConfigManager) VsanInternalSystem(ctx context.Context) (*HostVsanInternalSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.vsanInternalSystem"}, &h) + ref, err := m.reference(ctx, "vsanInternalSystem", true) // Added in 5.5 if err != nil { return nil, err } - - // Added in 5.5 - if h.ConfigManager.VsanInternalSystem == nil { - return nil, ErrNotSupported - } - - return NewHostVsanInternalSystem(m.c, *h.ConfigManager.VsanInternalSystem), nil + return NewHostVsanInternalSystem(m.c, ref), nil } func (m HostConfigManager) AccountManager(ctx context.Context) (*HostAccountManager, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.accountManager"}, &h) + ref, err := m.reference(ctx, "accountManager", true) // Added in 5.5 if err != nil { - return nil, err - } - - ref := h.ConfigManager.AccountManager // Added in 6.0 - if ref == nil { - // Versions < 5.5 can use the ServiceContent ref, - // but we can only use it when connected directly to ESX. - c := m.Client() - if !c.IsVC() { - ref = c.ServiceContent.AccountManager - } - - if ref == nil { - return nil, ErrNotSupported + if err == ErrNotSupported { + // Versions < 5.5 can use the ServiceContent ref, + // but only when connected directly to ESX. + if m.c.ServiceContent.AccountManager == nil { + return nil, err + } + ref = *m.c.ServiceContent.AccountManager + } else { + return nil, err } } - return NewHostAccountManager(m.c, *ref), nil + return NewHostAccountManager(m.c, ref), nil } func (m HostConfigManager) OptionManager(ctx context.Context) (*OptionManager, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.advancedOption"}, &h) + ref, err := m.reference(ctx, "advancedOption") if err != nil { return nil, err } - - return NewOptionManager(m.c, *h.ConfigManager.AdvancedOption), nil + return NewOptionManager(m.c, ref), nil } func (m HostConfigManager) ServiceSystem(ctx context.Context) (*HostServiceSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.serviceSystem"}, &h) + ref, err := m.reference(ctx, "serviceSystem") if err != nil { return nil, err } - - return NewHostServiceSystem(m.c, *h.ConfigManager.ServiceSystem), nil + return NewHostServiceSystem(m.c, ref), nil } func (m HostConfigManager) CertificateManager(ctx context.Context) (*HostCertificateManager, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.certificateManager"}, &h) + ref, err := m.reference(ctx, "certificateManager", true) // Added in 6.0 if err != nil { return nil, err } - - // Added in 6.0 - if h.ConfigManager.CertificateManager == nil { - return nil, ErrNotSupported - } - - return NewHostCertificateManager(m.c, *h.ConfigManager.CertificateManager, m.Reference()), nil + return NewHostCertificateManager(m.c, ref, m.Reference()), nil } func (m HostConfigManager) DateTimeSystem(ctx context.Context) (*HostDateTimeSystem, error) { - var h mo.HostSystem - - err := m.Properties(ctx, m.Reference(), []string{"configManager.dateTimeSystem"}, &h) + ref, err := m.reference(ctx, "dateTimeSystem") if err != nil { return nil, err } - - return NewHostDateTimeSystem(m.c, *h.ConfigManager.DateTimeSystem), nil + return NewHostDateTimeSystem(m.c, ref), nil } diff --git a/vendor/github.com/vmware/govmomi/object/host_datastore_system.go b/vendor/github.com/vmware/govmomi/object/host_datastore_system.go index 7b738e611e..64f3add917 100644 --- a/vendor/github.com/vmware/govmomi/object/host_datastore_system.go +++ b/vendor/github.com/vmware/govmomi/object/host_datastore_system.go @@ -117,3 +117,19 @@ func (s HostDatastoreSystem) QueryVmfsDatastoreCreateOptions(ctx context.Context return res.Returnval, nil } + +func (s HostDatastoreSystem) ResignatureUnresolvedVmfsVolumes(ctx context.Context, devicePaths []string) (*Task, error) { + req := &types.ResignatureUnresolvedVmfsVolume_Task{ + This: s.Reference(), + ResolutionSpec: types.HostUnresolvedVmfsResignatureSpec{ + ExtentDevicePath: devicePaths, + }, + } + + res, err := methods.ResignatureUnresolvedVmfsVolume_Task(ctx, s.Client(), req) + if err != nil { + return nil, err + } + + return NewTask(s.c, res.Returnval), nil +} diff --git a/vendor/github.com/vmware/govmomi/object/host_network_system.go b/vendor/github.com/vmware/govmomi/object/host_network_system.go index c21e1ec35d..340b764a51 100644 --- a/vendor/github.com/vmware/govmomi/object/host_network_system.go +++ b/vendor/github.com/vmware/govmomi/object/host_network_system.go @@ -98,18 +98,18 @@ func (o HostNetworkSystem) AddVirtualSwitch(ctx context.Context, vswitchName str } // QueryNetworkHint wraps methods.QueryNetworkHint -func (o HostNetworkSystem) QueryNetworkHint(ctx context.Context, device []string) error { +func (o HostNetworkSystem) QueryNetworkHint(ctx context.Context, device []string) ([]types.PhysicalNicHintInfo, error) { req := types.QueryNetworkHint{ This: o.Reference(), Device: device, } - _, err := methods.QueryNetworkHint(ctx, o.c, &req) + res, err := methods.QueryNetworkHint(ctx, o.c, &req) if err != nil { - return err + return nil, err } - return nil + return res.Returnval, err } // RefreshNetworkSystem wraps methods.RefreshNetworkSystem diff --git a/vendor/github.com/vmware/govmomi/object/host_storage_system.go b/vendor/github.com/vmware/govmomi/object/host_storage_system.go index 5990a1d4e6..5c9f08eee1 100644 --- a/vendor/github.com/vmware/govmomi/object/host_storage_system.go +++ b/vendor/github.com/vmware/govmomi/object/host_storage_system.go @@ -172,3 +172,29 @@ func (s HostStorageSystem) AttachScsiLun(ctx context.Context, uuid string) error return err } + +func (s HostStorageSystem) QueryUnresolvedVmfsVolumes(ctx context.Context) ([]types.HostUnresolvedVmfsVolume, error) { + req := &types.QueryUnresolvedVmfsVolume{ + This: s.Reference(), + } + + res, err := methods.QueryUnresolvedVmfsVolume(ctx, s.Client(), req) + if err != nil { + return nil, err + } + return res.Returnval, nil +} + +func (s HostStorageSystem) UnmountVmfsVolume(ctx context.Context, vmfsUuid string) error { + req := &types.UnmountVmfsVolume{ + This: s.Reference(), + VmfsUuid: vmfsUuid, + } + + _, err := methods.UnmountVmfsVolume(ctx, s.Client(), req) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/vmware/govmomi/object/host_system.go b/vendor/github.com/vmware/govmomi/object/host_system.go index a350edfdeb..ddf6cb8f11 100644 --- a/vendor/github.com/vmware/govmomi/object/host_system.go +++ b/vendor/github.com/vmware/govmomi/object/host_system.go @@ -21,6 +21,7 @@ import ( "fmt" "net" + "github.com/vmware/govmomi/internal" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/mo" @@ -81,17 +82,17 @@ func (h HostSystem) ManagementIPs(ctx context.Context) ([]net.IP, error) { return nil, err } - var ips []net.IP - for _, nc := range mh.Config.VirtualNicManagerInfo.NetConfig { - if nc.NicType == "management" && len(nc.CandidateVnic) > 0 { - ip := net.ParseIP(nc.CandidateVnic[0].Spec.Ip.IpAddress) - if ip != nil { - ips = append(ips, ip) - } - } + config := mh.Config + if config == nil { + return nil, nil } - return ips, nil + info := config.VirtualNicManagerInfo + if info == nil { + return nil, nil + } + + return internal.HostSystemManagementIPs(info.NetConfig), nil } func (h HostSystem) Disconnect(ctx context.Context) (*Task, error) { diff --git a/vendor/github.com/vmware/govmomi/object/network.go b/vendor/github.com/vmware/govmomi/object/network.go index d1dc7ce01f..f209a7ac4c 100644 --- a/vendor/github.com/vmware/govmomi/object/network.go +++ b/vendor/github.com/vmware/govmomi/object/network.go @@ -20,7 +20,6 @@ import ( "context" "github.com/vmware/govmomi/vim25" - "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -34,21 +33,20 @@ func NewNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Network { } } +func (n Network) GetInventoryPath() string { + return n.InventoryPath +} + // EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network func (n Network) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) { - var e mo.Network - - // Use Network.Name rather than Common.Name as the latter does not return the complete name if it contains a '/' - // We can't use Common.ObjectName here either as we need the ManagedEntity.Name field is not set since mo.Network - // has its own Name field. - err := n.Properties(ctx, n.Reference(), []string{"name"}, &e) + name, err := n.ObjectName(ctx) if err != nil { return nil, err } backing := &types.VirtualEthernetCardNetworkBackingInfo{ VirtualDeviceDeviceBackingInfo: types.VirtualDeviceDeviceBackingInfo{ - DeviceName: e.Name, + DeviceName: name, }, } diff --git a/vendor/github.com/vmware/govmomi/object/network_reference.go b/vendor/github.com/vmware/govmomi/object/network_reference.go index 7716bdb38f..f1a41cd59b 100644 --- a/vendor/github.com/vmware/govmomi/object/network_reference.go +++ b/vendor/github.com/vmware/govmomi/object/network_reference.go @@ -26,6 +26,6 @@ import ( // which can be used as the backing for a VirtualEthernetCard. type NetworkReference interface { Reference - + GetInventoryPath() string EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) } diff --git a/vendor/github.com/vmware/govmomi/object/opaque_network.go b/vendor/github.com/vmware/govmomi/object/opaque_network.go index 47ce4cefe6..6797d325de 100644 --- a/vendor/github.com/vmware/govmomi/object/opaque_network.go +++ b/vendor/github.com/vmware/govmomi/object/opaque_network.go @@ -35,19 +35,17 @@ func NewOpaqueNetwork(c *vim25.Client, ref types.ManagedObjectReference) *Opaque } } +func (n OpaqueNetwork) GetInventoryPath() string { + return n.InventoryPath +} + // EthernetCardBackingInfo returns the VirtualDeviceBackingInfo for this Network func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseVirtualDeviceBackingInfo, error) { - var net mo.OpaqueNetwork - - if err := n.Properties(ctx, n.Reference(), []string{"summary"}, &net); err != nil { + summary, err := n.Summary(ctx) + if err != nil { return nil, err } - summary, ok := net.Summary.(*types.OpaqueNetworkSummary) - if !ok { - return nil, fmt.Errorf("%s unsupported network type: %T", n, net.Summary) - } - backing := &types.VirtualEthernetCardOpaqueNetworkBackingInfo{ OpaqueNetworkId: summary.OpaqueNetworkId, OpaqueNetworkType: summary.OpaqueNetworkType, @@ -55,3 +53,20 @@ func (n OpaqueNetwork) EthernetCardBackingInfo(ctx context.Context) (types.BaseV return backing, nil } + +// Summary returns the mo.OpaqueNetwork.Summary property +func (n OpaqueNetwork) Summary(ctx context.Context) (*types.OpaqueNetworkSummary, error) { + var props mo.OpaqueNetwork + + err := n.Properties(ctx, n.Reference(), []string{"summary"}, &props) + if err != nil { + return nil, err + } + + summary, ok := props.Summary.(*types.OpaqueNetworkSummary) + if !ok { + return nil, fmt.Errorf("%s unsupported network summary type: %T", n, props.Summary) + } + + return summary, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/resource_pool.go b/vendor/github.com/vmware/govmomi/object/resource_pool.go index 55c2e2b2fd..e510006b40 100644 --- a/vendor/github.com/vmware/govmomi/object/resource_pool.go +++ b/vendor/github.com/vmware/govmomi/object/resource_pool.go @@ -22,6 +22,7 @@ import ( "github.com/vmware/govmomi/nfc" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" "github.com/vmware/govmomi/vim25/types" ) @@ -35,6 +36,18 @@ func NewResourcePool(c *vim25.Client, ref types.ManagedObjectReference) *Resourc } } +// Owner returns the ResourcePool owner as a ClusterComputeResource or ComputeResource. +func (p ResourcePool) Owner(ctx context.Context) (Reference, error) { + var pool mo.ResourcePool + + err := p.Properties(ctx, p.Reference(), []string{"owner"}, &pool) + if err != nil { + return nil, err + } + + return NewReference(p.Client(), pool.Owner), nil +} + func (p ResourcePool) ImportVApp(ctx context.Context, spec types.BaseImportSpec, folder *Folder, host *HostSystem) (*nfc.Lease, error) { req := types.ImportVApp{ This: p.Reference(), diff --git a/vendor/github.com/vmware/govmomi/object/search_index.go b/vendor/github.com/vmware/govmomi/object/search_index.go index 4b0a525d52..288f78097c 100644 --- a/vendor/github.com/vmware/govmomi/object/search_index.go +++ b/vendor/github.com/vmware/govmomi/object/search_index.go @@ -93,7 +93,18 @@ func (s SearchIndex) FindByInventoryPath(ctx context.Context, path string) (Refe if res.Returnval == nil { return nil, nil } - return NewReference(s.c, *res.Returnval), nil + + r := NewReference(s.c, *res.Returnval) + + type common interface { + SetInventoryPath(string) + } + + if c, ok := r.(common); ok { + c.SetInventoryPath(path) + } + + return r, nil } // FindByIp finds a virtual machine or host by IP address. @@ -161,3 +172,88 @@ func (s SearchIndex) FindChild(ctx context.Context, entity Reference, name strin } return NewReference(s.c, *res.Returnval), nil } + +// FindAllByDnsName finds all virtual machines or hosts by DNS name. +func (s SearchIndex) FindAllByDnsName(ctx context.Context, dc *Datacenter, dnsName string, vmSearch bool) ([]Reference, error) { + req := types.FindAllByDnsName{ + This: s.Reference(), + DnsName: dnsName, + VmSearch: vmSearch, + } + if dc != nil { + ref := dc.Reference() + req.Datacenter = &ref + } + + res, err := methods.FindAllByDnsName(ctx, s.c, &req) + if err != nil { + return nil, err + } + + if len(res.Returnval) == 0 { + return nil, nil + } + + var references []Reference + for _, returnval := range res.Returnval { + references = append(references, NewReference(s.c, returnval)) + } + return references, nil +} + +// FindAllByIp finds all virtual machines or hosts by IP address. +func (s SearchIndex) FindAllByIp(ctx context.Context, dc *Datacenter, ip string, vmSearch bool) ([]Reference, error) { + req := types.FindAllByIp{ + This: s.Reference(), + Ip: ip, + VmSearch: vmSearch, + } + if dc != nil { + ref := dc.Reference() + req.Datacenter = &ref + } + + res, err := methods.FindAllByIp(ctx, s.c, &req) + if err != nil { + return nil, err + } + + if len(res.Returnval) == 0 { + return nil, nil + } + + var references []Reference + for _, returnval := range res.Returnval { + references = append(references, NewReference(s.c, returnval)) + } + return references, nil +} + +// FindAllByUuid finds all virtual machines or hosts by UUID. +func (s SearchIndex) FindAllByUuid(ctx context.Context, dc *Datacenter, uuid string, vmSearch bool, instanceUuid *bool) ([]Reference, error) { + req := types.FindAllByUuid{ + This: s.Reference(), + Uuid: uuid, + VmSearch: vmSearch, + InstanceUuid: instanceUuid, + } + if dc != nil { + ref := dc.Reference() + req.Datacenter = &ref + } + + res, err := methods.FindAllByUuid(ctx, s.c, &req) + if err != nil { + return nil, err + } + + if len(res.Returnval) == 0 { + return nil, nil + } + + var references []Reference + for _, returnval := range res.Returnval { + references = append(references, NewReference(s.c, returnval)) + } + return references, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/task.go b/vendor/github.com/vmware/govmomi/object/task.go index 2b66aa93b7..583bcc6e01 100644 --- a/vendor/github.com/vmware/govmomi/object/task.go +++ b/vendor/github.com/vmware/govmomi/object/task.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2024 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 +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, @@ -18,6 +18,7 @@ package object import ( "context" + "fmt" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/task" @@ -43,14 +44,63 @@ func NewTask(c *vim25.Client, ref types.ManagedObjectReference) *Task { return &t } +// Wait waits for a task to complete. +// NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe. +// The downside of this approach is the additional resource usage on the vCenter side for each call. func (t *Task) Wait(ctx context.Context) error { _, err := t.WaitForResult(ctx, nil) return err } -func (t *Task) WaitForResult(ctx context.Context, s progress.Sinker) (*types.TaskInfo, error) { +// WaitForResult wait for a task to complete. +// NOTE: This method create a thread-safe PropertyCollector instance per-call, so it is thread safe. +// The downside of this approach is the additional resource usage on the vCenter side for each call. +func (t *Task) WaitForResult(ctx context.Context, s ...progress.Sinker) (taskInfo *types.TaskInfo, result error) { + var pr progress.Sinker + if len(s) == 1 { + pr = s[0] + } + p, err := property.DefaultCollector(t.c).Create(ctx) + if err != nil { + return nil, err + } + + // Attempt to destroy the collector using the background context, as the + // specified context may have timed out or have been canceled. + defer func() { + if err := p.Destroy(context.Background()); err != nil { + if result == nil { + result = err + } else { + result = fmt.Errorf( + "destroy property collector failed with %s after failing to wait for updates: %w", + err, + result) + } + } + }() + + return task.WaitEx(ctx, t.Reference(), p, pr) +} + +// WaitEx waits for a task to complete. +// NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side. +// The downside of this approach is that this method is not thread safe. +func (t *Task) WaitEx(ctx context.Context) error { + _, err := t.WaitForResultEx(ctx, nil) + return err +} + +// WaitForResultEx waits for a task to complete. +// NOTE: This method use the same PropertyCollector instance in each call, thus reducing resource usage on the vCenter side. +// The downside of this approach is that this method is not thread safe. +func (t *Task) WaitForResultEx(ctx context.Context, s ...progress.Sinker) (*types.TaskInfo, error) { + var pr progress.Sinker + if len(s) == 1 { + pr = s[0] + } p := property.DefaultCollector(t.c) - return task.Wait(ctx, t.Reference(), p, s) + return task.WaitEx(ctx, t.Reference(), p, pr) } func (t *Task) Cancel(ctx context.Context) error { @@ -60,3 +110,37 @@ func (t *Task) Cancel(ctx context.Context) error { return err } + +// SetState sets task state and optionally sets results or fault, as appropriate for state. +func (t *Task) SetState(ctx context.Context, state types.TaskInfoState, result types.AnyType, fault *types.LocalizedMethodFault) error { + req := types.SetTaskState{ + This: t.Reference(), + State: state, + Result: result, + Fault: fault, + } + _, err := methods.SetTaskState(ctx, t.Common.Client(), &req) + return err +} + +// SetDescription updates task description to describe the current phase of the task. +func (t *Task) SetDescription(ctx context.Context, description types.LocalizableMessage) error { + req := types.SetTaskDescription{ + This: t.Reference(), + Description: description, + } + _, err := methods.SetTaskDescription(ctx, t.Common.Client(), &req) + return err +} + +// UpdateProgress Sets percentage done for this task and recalculates overall percentage done. +// If a percentDone value of less than zero or greater than 100 is specified, +// a value of zero or 100 respectively is used. +func (t *Task) UpdateProgress(ctx context.Context, percentDone int) error { + req := types.UpdateProgress{ + This: t.Reference(), + PercentDone: int32(percentDone), + } + _, err := methods.UpdateProgress(ctx, t.Common.Client(), &req) + return err +} diff --git a/vendor/github.com/vmware/govmomi/object/tenant_manager.go b/vendor/github.com/vmware/govmomi/object/tenant_manager.go new file mode 100644 index 0000000000..4dda196e35 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/object/tenant_manager.go @@ -0,0 +1,78 @@ +/* +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 object + +import ( + "context" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +type TenantManager struct { + Common +} + +func NewTenantManager(c *vim25.Client) *TenantManager { + t := TenantManager{ + Common: NewCommon(c, *c.ServiceContent.TenantManager), + } + + return &t +} + +func (t TenantManager) MarkServiceProviderEntities(ctx context.Context, entities []types.ManagedObjectReference) error { + req := types.MarkServiceProviderEntities{ + This: t.Reference(), + Entity: entities, + } + + _, err := methods.MarkServiceProviderEntities(ctx, t.Client(), &req) + if err != nil { + return err + } + + return nil +} + +func (t TenantManager) UnmarkServiceProviderEntities(ctx context.Context, entities []types.ManagedObjectReference) error { + req := types.UnmarkServiceProviderEntities{ + This: t.Reference(), + Entity: entities, + } + + _, err := methods.UnmarkServiceProviderEntities(ctx, t.Client(), &req) + if err != nil { + return err + } + + return nil +} + +func (t TenantManager) RetrieveServiceProviderEntities(ctx context.Context) ([]types.ManagedObjectReference, error) { + req := types.RetrieveServiceProviderEntities{ + This: t.Reference(), + } + + res, err := methods.RetrieveServiceProviderEntities(ctx, t.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/virtual_app.go b/vendor/github.com/vmware/govmomi/object/virtual_app.go index 4811178f16..b7311b3e39 100644 --- a/vendor/github.com/vmware/govmomi/object/virtual_app.go +++ b/vendor/github.com/vmware/govmomi/object/virtual_app.go @@ -103,3 +103,19 @@ func (p VirtualApp) Suspend(ctx context.Context) (*Task, error) { return NewTask(p.c, res.Returnval), nil } + +func (p VirtualApp) Clone(ctx context.Context, name string, target types.ManagedObjectReference, spec types.VAppCloneSpec) (*Task, error) { + req := types.CloneVApp_Task{ + This: p.Reference(), + Name: name, + Target: target, + Spec: spec, + } + + res, err := methods.CloneVApp_Task(ctx, p.c, &req) + if err != nil { + return nil, err + } + + return NewTask(p.c, res.Returnval), nil +} diff --git a/vendor/github.com/vmware/govmomi/object/virtual_device_list.go b/vendor/github.com/vmware/govmomi/object/virtual_device_list.go index e1c35eff88..92797dcdab 100644 --- a/vendor/github.com/vmware/govmomi/object/virtual_device_list.go +++ b/vendor/github.com/vmware/govmomi/object/virtual_device_list.go @@ -19,6 +19,7 @@ package object import ( "errors" "fmt" + "math/rand" "path/filepath" "reflect" "regexp" @@ -63,11 +64,12 @@ func EthernetCardTypes() VirtualDeviceList { &types.VirtualE1000e{}, &types.VirtualVmxnet2{}, &types.VirtualVmxnet3{}, + &types.VirtualVmxnet3Vrdma{}, &types.VirtualPCNet32{}, &types.VirtualSriovEthernetCard{}, }).Select(func(device types.BaseVirtualDevice) bool { c := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard() - c.GetVirtualDevice().Key = -1 + c.GetVirtualDevice().Key = VirtualDeviceList{}.newRandomKey() return true }) } @@ -134,6 +136,9 @@ func (l VirtualDeviceList) SelectByBackingInfo(backing types.BaseVirtualDeviceBa b := backing.(*types.VirtualEthernetCardDistributedVirtualPortBackingInfo) return a.Port.SwitchUuid == b.Port.SwitchUuid && a.Port.PortgroupKey == b.Port.PortgroupKey + case *types.VirtualEthernetCardOpaqueNetworkBackingInfo: + b := backing.(*types.VirtualEthernetCardOpaqueNetworkBackingInfo) + return a.OpaqueNetworkId == b.OpaqueNetworkId case *types.VirtualDiskFlatVer2BackingInfo: b := backing.(*types.VirtualDiskFlatVer2BackingInfo) if a.Parent != nil && b.Parent != nil { @@ -146,6 +151,25 @@ func (l VirtualDeviceList) SelectByBackingInfo(backing types.BaseVirtualDeviceBa case types.BaseVirtualDeviceFileBackingInfo: b := backing.(types.BaseVirtualDeviceFileBackingInfo) return a.GetVirtualDeviceFileBackingInfo().FileName == b.GetVirtualDeviceFileBackingInfo().FileName + case *types.VirtualPCIPassthroughVmiopBackingInfo: + b := backing.(*types.VirtualPCIPassthroughVmiopBackingInfo) + return a.Vgpu == b.Vgpu + case *types.VirtualPCIPassthroughDynamicBackingInfo: + b := backing.(*types.VirtualPCIPassthroughDynamicBackingInfo) + if b.CustomLabel != "" && b.CustomLabel != a.CustomLabel { + return false + } + if len(b.AllowedDevice) == 0 { + return true + } + for _, x := range a.AllowedDevice { + for _, y := range b.AllowedDevice { + if x.DeviceId == y.DeviceId && x.VendorId == y.VendorId { + return true + } + } + } + return false default: return false } @@ -229,8 +253,10 @@ func (l VirtualDeviceList) FindSCSIController(name string) (*types.VirtualSCSICo func (l VirtualDeviceList) CreateSCSIController(name string) (types.BaseVirtualDevice, error) { ctypes := SCSIControllerTypes() - if name == "scsi" || name == "" { + if name == "" || name == "scsi" { name = ctypes.Type(ctypes[0]) + } else if name == "virtualscsi" { + name = "pvscsi" // ovf VirtualSCSI mapping } found := ctypes.Select(func(device types.BaseVirtualDevice) bool { @@ -378,9 +404,13 @@ func (l VirtualDeviceList) PickController(kind types.BaseVirtualController) type } // newUnitNumber returns the unit number to use for attaching a new device to the given controller. -func (l VirtualDeviceList) newUnitNumber(c types.BaseVirtualController) int32 { +func (l VirtualDeviceList) newUnitNumber(c types.BaseVirtualController, offset int) int32 { units := make([]bool, 30) + for i := 0; i < offset; i++ { + units[i] = true + } + switch sc := c.(type) { case types.BaseVirtualSCSIController: // The SCSI controller sits on its own bus @@ -429,10 +459,29 @@ func (l VirtualDeviceList) AssignController(device types.BaseVirtualDevice, c ty d := device.GetVirtualDevice() d.ControllerKey = c.GetVirtualController().Key d.UnitNumber = new(int32) - *d.UnitNumber = l.newUnitNumber(c) - if d.Key == 0 { - d.Key = -1 + + offset := 0 + switch device.(type) { + case types.BaseVirtualEthernetCard: + offset = 7 } + *d.UnitNumber = l.newUnitNumber(c, offset) + + if d.Key == 0 { + d.Key = l.newRandomKey() + } +} + +// newRandomKey returns a random negative device key. +// The generated key can be used for devices you want to add so that it does not collide with existing ones. +func (l VirtualDeviceList) newRandomKey() int32 { + // NOTE: rand.Uint32 cannot be used here because conversion from uint32 to int32 may change the sign + key := rand.Int31() * -1 + if key == 0 { + return -1 + } + + return key } // CreateDisk creates a new VirtualDisk device which can be added to a VM. @@ -862,6 +911,8 @@ func (l VirtualDeviceList) Type(device types.BaseVirtualDevice) string { return "lsilogic-sas" case *types.VirtualNVMEController: return "nvme" + case *types.VirtualPrecisionClock: + return "clock" default: return l.deviceName(device) } @@ -879,7 +930,13 @@ func (l VirtualDeviceList) Name(device types.BaseVirtualDevice) string { dtype := l.Type(device) switch dtype { case DeviceTypeEthernet: - key = fmt.Sprintf("%d", UnitNumber-7) + // Ethernet devices of UnitNumber 7-19 are non-SRIOV. Ethernet devices of + // UnitNumber 45-36 descending are SRIOV + if UnitNumber <= 45 && UnitNumber >= 36 { + key = fmt.Sprintf("sriov-%d", 45-UnitNumber) + } else { + key = fmt.Sprintf("%d", UnitNumber-7) + } case DeviceTypeDisk: key = fmt.Sprintf("%d-%d", d.ControllerKey, UnitNumber) default: @@ -907,25 +964,9 @@ func (l VirtualDeviceList) ConfigSpec(op types.VirtualDeviceConfigSpecOperation) var res []types.BaseVirtualDeviceConfigSpec for _, device := range l { config := &types.VirtualDeviceConfigSpec{ - Device: device, - Operation: op, - } - - if disk, ok := device.(*types.VirtualDisk); ok { - config.FileOperation = fop - - // Special case to attach an existing disk - if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 { - childDisk := false - if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok { - childDisk = b.Parent != nil - } - - if !childDisk { - // Existing disk, clear file operation - config.FileOperation = "" - } - } + Device: device, + Operation: op, + FileOperation: diskFileOperation(op, fop, device), } res = append(res, config) diff --git a/vendor/github.com/vmware/govmomi/object/virtual_machine.go b/vendor/github.com/vmware/govmomi/object/virtual_machine.go index ba22e554f3..4665fcb744 100644 --- a/vendor/github.com/vmware/govmomi/object/virtual_machine.go +++ b/vendor/github.com/vmware/govmomi/object/virtual_machine.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 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 +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, @@ -22,6 +22,7 @@ import ( "fmt" "net" "path" + "strings" "github.com/vmware/govmomi/nfc" "github.com/vmware/govmomi/property" @@ -33,12 +34,41 @@ import ( const ( PropRuntimePowerState = "summary.runtime.powerState" + PropConfigTemplate = "summary.config.template" ) type VirtualMachine struct { Common } +// extractDiskLayoutFiles is a helper function used to extract file keys for +// all disk files attached to the virtual machine at the current point of +// running. +func extractDiskLayoutFiles(diskLayoutList []types.VirtualMachineFileLayoutExDiskLayout) []int { + var result []int + + for _, layoutExDisk := range diskLayoutList { + for _, link := range layoutExDisk.Chain { + for i := range link.FileKey { // diskDescriptor, diskExtent pairs + result = append(result, int(link.FileKey[i])) + } + } + } + + return result +} + +// removeKey is a helper function for removing a specific file key from a list +// of keys associated with disks attached to a virtual machine. +func removeKey(l *[]int, key int) { + for i, k := range *l { + if k == key { + *l = append((*l)[:i], (*l)[i+1:]...) + break + } + } +} + func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine { return &VirtualMachine{ Common: NewCommon(c, ref), @@ -56,6 +86,17 @@ func (v VirtualMachine) PowerState(ctx context.Context) (types.VirtualMachinePow return o.Summary.Runtime.PowerState, nil } +func (v VirtualMachine) IsTemplate(ctx context.Context) (bool, error) { + var o mo.VirtualMachine + + err := v.Properties(ctx, v.Reference(), []string{PropConfigTemplate}, &o) + if err != nil { + return false, err + } + + return o.Summary.Config.Template, nil +} + func (v VirtualMachine) PowerOn(ctx context.Context) (*Task, error) { req := types.PowerOnVM_Task{ This: v.Reference(), @@ -131,6 +172,15 @@ func (v VirtualMachine) ShutdownGuest(ctx context.Context) error { return err } +func (v VirtualMachine) StandbyGuest(ctx context.Context) error { + req := types.StandbyGuest{ + This: v.Reference(), + } + + _, err := methods.StandbyGuest(ctx, v.c, &req) + return err +} + func (v VirtualMachine) RebootGuest(ctx context.Context) error { req := types.RebootGuest{ This: v.Reference(), @@ -169,6 +219,20 @@ func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string, return NewTask(v.c, res.Returnval), nil } +func (v VirtualMachine) InstantClone(ctx context.Context, config types.VirtualMachineInstantCloneSpec) (*Task, error) { + req := types.InstantClone_Task{ + This: v.Reference(), + Spec: config, + } + + res, err := methods.InstantClone_Task(ctx, v.c, &req) + if err != nil { + return nil, err + } + + return NewTask(v.c, res.Returnval), nil +} + func (v VirtualMachine) Customize(ctx context.Context, spec types.CustomizationSpec) (*Task, error) { req := types.CustomizeVM_Task{ This: v.Reference(), @@ -221,7 +285,9 @@ func (v VirtualMachine) RefreshStorageInfo(ctx context.Context) error { return err } -func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) { +// WaitForIP waits for the VM guest.ipAddress property to report an IP address. +// Waits for an IPv4 address if the v4 param is true. +func (v VirtualMachine) WaitForIP(ctx context.Context, v4 ...bool) (string, error) { var ip string p := property.DefaultCollector(v.c) @@ -238,6 +304,11 @@ func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) { } ip = c.Val.(string) + if len(v4) == 1 && v4[0] { + if net.ParseIP(ip).To4() == nil { + return false + } + } return true } @@ -272,7 +343,9 @@ func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...str devices := VirtualDeviceList(c.Val.(types.ArrayOfVirtualDevice).VirtualDevice) for _, d := range devices { if nic, ok := d.(types.BaseVirtualEthernetCard); ok { - mac := nic.GetVirtualEthernetCard().MacAddress + // Convert to lower so that e.g. 00:50:56:83:3A:5D is treated the + // same as 00:50:56:83:3a:5d + mac := strings.ToLower(nic.GetVirtualEthernetCard().MacAddress) if mac == "" { return false } @@ -285,6 +358,10 @@ func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...str return true }) + if err != nil { + return nil, err + } + if len(device) != 0 { // Only wait for specific NIC(s) macs = make(map[string][]string) @@ -304,7 +381,9 @@ func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...str nics := c.Val.(types.ArrayOfGuestNicInfo).GuestNicInfo for _, nic := range nics { - mac := nic.MacAddress + // Convert to lower so that e.g. 00:50:56:83:3A:5D is treated the + // same as 00:50:56:83:3a:5d + mac := strings.ToLower(nic.MacAddress) if mac == "" || nic.IpConfig == nil { continue } @@ -359,6 +438,17 @@ func (v VirtualMachine) Device(ctx context.Context) (VirtualDeviceList, error) { return VirtualDeviceList(o.Config.Hardware.Device), nil } +func (v VirtualMachine) EnvironmentBrowser(ctx context.Context) (*EnvironmentBrowser, error) { + var vm mo.VirtualMachine + + err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm) + if err != nil { + return nil, err + } + + return NewEnvironmentBrowser(v.c, vm.EnvironmentBrowser), nil +} + func (v VirtualMachine) HostSystem(ctx context.Context) (*HostSystem, error) { var o mo.VirtualMachine @@ -391,29 +481,33 @@ func (v VirtualMachine) ResourcePool(ctx context.Context) (*ResourcePool, error) return NewResourcePool(v.c, *rp), nil } +func diskFileOperation(op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, device types.BaseVirtualDevice) types.VirtualDeviceConfigSpecFileOperation { + if disk, ok := device.(*types.VirtualDisk); ok { + // Special case to attach an existing disk + if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 && disk.CapacityInBytes == 0 { + childDisk := false + if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok { + childDisk = b.Parent != nil + } + + if !childDisk { + fop = "" // existing disk + } + } + return fop + } + + return "" +} + func (v VirtualMachine) configureDevice(ctx context.Context, op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, devices ...types.BaseVirtualDevice) error { spec := types.VirtualMachineConfigSpec{} for _, device := range devices { config := &types.VirtualDeviceConfigSpec{ - Device: device, - Operation: op, - } - - if disk, ok := device.(*types.VirtualDisk); ok { - config.FileOperation = fop - - // Special case to attach an existing disk - if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 { - childDisk := false - if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok { - childDisk = b.Parent != nil - } - - if !childDisk { - config.FileOperation = "" // existing disk - } - } + Device: device, + Operation: op, + FileOperation: diskFileOperation(op, fop, device), } spec.DeviceChange = append(spec.DeviceChange, config) @@ -446,6 +540,41 @@ func (v VirtualMachine) RemoveDevice(ctx context.Context, keepFiles bool, device return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationRemove, fop, device...) } +// AttachDisk attaches the given disk to the VirtualMachine +func (v VirtualMachine) AttachDisk(ctx context.Context, id string, datastore *Datastore, controllerKey int32, unitNumber int32) error { + req := types.AttachDisk_Task{ + This: v.Reference(), + DiskId: types.ID{Id: id}, + Datastore: datastore.Reference(), + ControllerKey: controllerKey, + UnitNumber: &unitNumber, + } + + res, err := methods.AttachDisk_Task(ctx, v.c, &req) + if err != nil { + return err + } + + task := NewTask(v.c, res.Returnval) + return task.Wait(ctx) +} + +// DetachDisk detaches the given disk from the VirtualMachine +func (v VirtualMachine) DetachDisk(ctx context.Context, id string) error { + req := types.DetachDisk_Task{ + This: v.Reference(), + DiskId: types.ID{Id: id}, + } + + res, err := methods.DetachDisk_Task(ctx, v.c, &req) + if err != nil { + return err + } + + task := NewTask(v.c, res.Returnval) + return task.Wait(ctx) +} + // BootOptions returns the VirtualMachine's config.bootOptions property. func (v VirtualMachine) BootOptions(ctx context.Context) (*types.VirtualMachineBootOptions, error) { var o mo.VirtualMachine @@ -556,6 +685,63 @@ func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree) } } +// SnapshotSize calculates the size of a given snapshot in bytes. If the +// snapshot is current, disk files not associated with any parent snapshot are +// included in size calculations. This allows for measuring and including the +// growth from the last fixed snapshot to the present state. +func SnapshotSize(info types.ManagedObjectReference, parent *types.ManagedObjectReference, vmlayout *types.VirtualMachineFileLayoutEx, isCurrent bool) int { + var fileKeyList []int + var parentFiles []int + var allSnapshotFiles []int + + diskFiles := extractDiskLayoutFiles(vmlayout.Disk) + + for _, layout := range vmlayout.Snapshot { + diskLayout := extractDiskLayoutFiles(layout.Disk) + allSnapshotFiles = append(allSnapshotFiles, diskLayout...) + + if layout.Key.Value == info.Value { + fileKeyList = append(fileKeyList, int(layout.DataKey)) // The .vmsn file + fileKeyList = append(fileKeyList, diskLayout...) // The .vmdk files + } else if parent != nil && layout.Key.Value == parent.Value { + parentFiles = append(parentFiles, diskLayout...) + } + } + + for _, parentFile := range parentFiles { + removeKey(&fileKeyList, parentFile) + } + + for _, file := range allSnapshotFiles { + removeKey(&diskFiles, file) + } + + fileKeyMap := make(map[int]types.VirtualMachineFileLayoutExFileInfo) + for _, file := range vmlayout.File { + fileKeyMap[int(file.Key)] = file + } + + size := 0 + + for _, fileKey := range fileKeyList { + file := fileKeyMap[fileKey] + if parent != nil || + (file.Type != string(types.VirtualMachineFileLayoutExFileTypeDiskDescriptor) && + file.Type != string(types.VirtualMachineFileLayoutExFileTypeDiskExtent)) { + size += int(file.Size) + } + } + + if isCurrent { + for _, diskFile := range diskFiles { + file := fileKeyMap[diskFile] + size += int(file.Size) + } + } + + return size +} + // FindSnapshot supports snapshot lookup by name, where name can be: // 1) snapshot ManagedObjectReference.Value (unique) // 2) snapshot name (may not be unique) @@ -569,7 +755,7 @@ func (v VirtualMachine) FindSnapshot(ctx context.Context, name string) (*types.M } if o.Snapshot == nil || len(o.Snapshot.RootSnapshotList) == 0 { - return nil, errors.New("No snapshots for this VM") + return nil, errors.New("no snapshots for this VM") } m := make(snapshotMap) @@ -743,27 +929,6 @@ func (v VirtualMachine) Unregister(ctx context.Context) error { return err } -// QueryEnvironmentBrowser is a helper to get the environmentBrowser property. -func (v VirtualMachine) QueryConfigTarget(ctx context.Context) (*types.ConfigTarget, error) { - var vm mo.VirtualMachine - - err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm) - if err != nil { - return nil, err - } - - req := types.QueryConfigTarget{ - This: vm.EnvironmentBrowser, - } - - res, err := methods.QueryConfigTarget(ctx, v.Client(), &req) - if err != nil { - return nil, err - } - - return res.Returnval, nil -} - func (v VirtualMachine) MountToolsInstaller(ctx context.Context) error { req := types.MountToolsInstaller{ This: v.Reference(), @@ -832,6 +997,85 @@ func (v VirtualMachine) UUID(ctx context.Context) string { if err != nil { return "" } + if o.Config != nil { + return o.Config.Uuid + } + return "" +} - return o.Config.Uuid +func (v VirtualMachine) QueryChangedDiskAreas(ctx context.Context, baseSnapshot, curSnapshot *types.ManagedObjectReference, disk *types.VirtualDisk, offset int64) (types.DiskChangeInfo, error) { + var noChange types.DiskChangeInfo + var err error + + if offset > disk.CapacityInBytes { + return noChange, fmt.Errorf("offset is greater than the disk size (%#x and %#x)", offset, disk.CapacityInBytes) + } else if offset == disk.CapacityInBytes { + return types.DiskChangeInfo{StartOffset: offset, Length: 0}, nil + } + + var b mo.VirtualMachineSnapshot + err = v.Properties(ctx, baseSnapshot.Reference(), []string{"config.hardware"}, &b) + if err != nil { + return noChange, fmt.Errorf("failed to fetch config.hardware of snapshot %s: %s", baseSnapshot, err) + } + + var changeId *string + for _, vd := range b.Config.Hardware.Device { + d := vd.GetVirtualDevice() + if d.Key != disk.Key { + continue + } + + // As per VDDK programming guide, these are the four types of disks + // that support CBT, see "Gathering Changed Block Information". + if b, ok := d.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok { + changeId = &b.ChangeId + break + } + if b, ok := d.Backing.(*types.VirtualDiskSparseVer2BackingInfo); ok { + changeId = &b.ChangeId + break + } + if b, ok := d.Backing.(*types.VirtualDiskRawDiskMappingVer1BackingInfo); ok { + changeId = &b.ChangeId + break + } + if b, ok := d.Backing.(*types.VirtualDiskRawDiskVer2BackingInfo); ok { + changeId = &b.ChangeId + break + } + + return noChange, fmt.Errorf("disk %d has backing info without .ChangeId: %t", disk.Key, d.Backing) + } + if changeId == nil || *changeId == "" { + return noChange, fmt.Errorf("CBT is not enabled on disk %d", disk.Key) + } + + req := types.QueryChangedDiskAreas{ + This: v.Reference(), + Snapshot: curSnapshot, + DeviceKey: disk.Key, + StartOffset: offset, + ChangeId: *changeId, + } + + res, err := methods.QueryChangedDiskAreas(ctx, v.Client(), &req) + if err != nil { + return noChange, err + } + + return res.Returnval, nil +} + +// ExportSnapshot exports all VMDK-files up to (but not including) a specified snapshot. This +// is useful when exporting a running VM. +func (v *VirtualMachine) ExportSnapshot(ctx context.Context, snapshot *types.ManagedObjectReference) (*nfc.Lease, error) { + req := types.ExportSnapshot{ + This: *snapshot, + } + resp, err := methods.ExportSnapshot(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + return nfc.NewLease(v.c, resp.Returnval), nil } diff --git a/vendor/github.com/vmware/govmomi/object/vmware_distributed_virtual_switch.go b/vendor/github.com/vmware/govmomi/object/vmware_distributed_virtual_switch.go index f6caf98708..8eccba19b1 100644 --- a/vendor/github.com/vmware/govmomi/object/vmware_distributed_virtual_switch.go +++ b/vendor/github.com/vmware/govmomi/object/vmware_distributed_virtual_switch.go @@ -19,3 +19,7 @@ package object type VmwareDistributedVirtualSwitch struct { DistributedVirtualSwitch } + +func (s VmwareDistributedVirtualSwitch) GetInventoryPath() string { + return s.InventoryPath +} diff --git a/vendor/github.com/vmware/govmomi/ovf/cim.go b/vendor/github.com/vmware/govmomi/ovf/cim.go index ce20bde19f..427699954c 100644 --- a/vendor/github.com/vmware/govmomi/ovf/cim.go +++ b/vendor/github.com/vmware/govmomi/ovf/cim.go @@ -16,6 +16,10 @@ limitations under the License. package ovf +import ( + "github.com/vmware/govmomi/vim25/types" +) + /* Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_VirtualSystemSettingData.xsd */ @@ -76,3 +80,49 @@ type CIMResourceAllocationSettingData struct { VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"` Weight *uint `xml:"Weight"` } + +/* +Source: http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2.24.0/CIM_StorageAllocationSettingData.xsd +*/ +type CIMStorageAllocationSettingData struct { + ElementName string `xml:"ElementName"` + InstanceID string `xml:"InstanceID"` + + ResourceType *uint16 `xml:"ResourceType"` + OtherResourceType *string `xml:"OtherResourceType"` + ResourceSubType *string `xml:"ResourceSubType"` + + Access *uint16 `xml:"Access"` + Address *string `xml:"Address"` + AddressOnParent *string `xml:"AddressOnParent"` + AllocationUnits *string `xml:"AllocationUnits"` + AutomaticAllocation *bool `xml:"AutomaticAllocation"` + AutomaticDeallocation *bool `xml:"AutomaticDeallocation"` + Caption *string `xml:"Caption"` + ChangeableType *uint16 `xml:"ChangeableType"` + ComponentSetting []types.AnyType `xml:"ComponentSetting"` + ConfigurationName *string `xml:"ConfigurationName"` + Connection []string `xml:"Connection"` + ConsumerVisibility *uint16 `xml:"ConsumerVisibility"` + Description *string `xml:"Description"` + Generation *uint64 `xml:"Generation"` + HostExtentName *string `xml:"HostExtentName"` + HostExtentNameFormat *uint16 `xml:"HostExtentNameFormat"` + HostExtentNameNamespace *uint16 `xml:"HostExtentNameNamespace"` + HostExtentStartingAddress *uint64 `xml:"HostExtentStartingAddress"` + HostResource []string `xml:"HostResource"` + HostResourceBlockSize *uint64 `xml:"HostResourceBlockSize"` + Limit *uint64 `xml:"Limit"` + MappingBehavior *uint `xml:"MappingBehavior"` + OtherHostExtentNameFormat *string `xml:"OtherHostExtentNameFormat"` + OtherHostExtentNameNamespace *string `xml:"OtherHostExtentNameNamespace"` + Parent *string `xml:"Parent"` + PoolID *string `xml:"PoolID"` + Reservation *uint64 `xml:"Reservation"` + SoID *string `xml:"SoID"` + SoOrgID *string `xml:"SoOrgID"` + VirtualQuantity *uint `xml:"VirtualQuantity"` + VirtualQuantityUnits *string `xml:"VirtualQuantityUnits"` + VirtualResourceBlockSize *uint64 `xml:"VirtualResourceBlockSize"` + Weight *uint `xml:"Weight"` +} diff --git a/vendor/github.com/vmware/govmomi/ovf/env.go b/vendor/github.com/vmware/govmomi/ovf/env.go index 584564ab77..3ec1b99d00 100644 --- a/vendor/github.com/vmware/govmomi/ovf/env.go +++ b/vendor/github.com/vmware/govmomi/ovf/env.go @@ -87,13 +87,13 @@ func (e Env) MarshalManual() string { buffer.WriteString(fmt.Sprintf(ovfEnvHeader, e.EsxID)) buffer.WriteString(fmt.Sprintf(ovfEnvPlatformSection, e.Platform.Kind, e.Platform.Version, e.Platform.Vendor, e.Platform.Locale)) - buffer.WriteString(fmt.Sprintf(ovfEnvPropertyHeader)) + buffer.WriteString(fmt.Sprint(ovfEnvPropertyHeader)) for _, p := range e.Property.Properties { buffer.WriteString(fmt.Sprintf(ovfEnvPropertyEntry, p.Key, p.Value)) } - buffer.WriteString(fmt.Sprintf(ovfEnvPropertyFooter)) + buffer.WriteString(fmt.Sprint(ovfEnvPropertyFooter)) - buffer.WriteString(fmt.Sprintf(ovfEnvFooter)) + buffer.WriteString(fmt.Sprint(ovfEnvFooter)) return buffer.String() } diff --git a/vendor/github.com/vmware/govmomi/ovf/envelope.go b/vendor/github.com/vmware/govmomi/ovf/envelope.go index d8b6fd8953..aa77aab2de 100644 --- a/vendor/github.com/vmware/govmomi/ovf/envelope.go +++ b/vendor/github.com/vmware/govmomi/ovf/envelope.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 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 +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, @@ -16,6 +16,10 @@ limitations under the License. package ovf +import ( + "fmt" +) + type Envelope struct { References []File `xml:"References>File"` @@ -61,6 +65,7 @@ type Content struct { type Section struct { Required *bool `xml:"required,attr"` Info string `xml:"Info"` + Category string `xml:"Category"` } type AnnotationSection struct { @@ -85,6 +90,20 @@ type ProductSection struct { Property []Property `xml:"Property"` } +func (p ProductSection) Key(prop Property) string { + // From OVF spec, section 9.5.1: + // key-value-env = [class-value "."] key-value-prod ["." instance-value] + + k := prop.Key + if p.Class != nil { + k = fmt.Sprintf("%s.%s", *p.Class, k) + } + if p.Instance != nil { + k = fmt.Sprintf("%s.%s", k, *p.Instance) + } + return k +} + type Property struct { Key string `xml:"key,attr"` Type string `xml:"type,attr"` @@ -148,14 +167,23 @@ type EulaSection struct { License string `xml:"License"` } +type Config struct { + Required *bool `xml:"required,attr"` + Key string `xml:"key,attr"` + Value string `xml:"value,attr"` +} + type VirtualHardwareSection struct { Section ID *string `xml:"id,attr"` Transport *string `xml:"transport,attr"` - System *VirtualSystemSettingData `xml:"System"` - Item []ResourceAllocationSettingData `xml:"Item"` + System *VirtualSystemSettingData `xml:"System"` + Item []ResourceAllocationSettingData `xml:"Item"` + StorageItem []StorageAllocationSettingData `xml:"StorageItem"` + Config []Config `xml:"Config"` + ExtraConfig []Config `xml:"ExtraConfig"` } type VirtualSystemSettingData struct { @@ -170,6 +198,14 @@ type ResourceAllocationSettingData struct { Bound *string `xml:"bound,attr"` } +type StorageAllocationSettingData struct { + CIMStorageAllocationSettingData + + Required *bool `xml:"required,attr"` + Configuration *string `xml:"configuration,attr"` + Bound *string `xml:"bound,attr"` +} + type ResourceAllocationSection struct { Section diff --git a/vendor/github.com/vmware/govmomi/performance/manager.go b/vendor/github.com/vmware/govmomi/performance/manager.go index eabd0f417b..94b9c79514 100644 --- a/vendor/github.com/vmware/govmomi/performance/manager.go +++ b/vendor/github.com/vmware/govmomi/performance/manager.go @@ -32,6 +32,17 @@ import ( "github.com/vmware/govmomi/vim25/types" ) +var ( + // Intervals maps name to seconds for the built-in historical intervals + Intervals = map[string]int32{ + "real": 0, // 0 == default 20s interval + "day": 300, + "week": 1800, + "month": 7200, + "year": 86400, + } +) + // Manager wraps mo.PerformanceManager. type Manager struct { object.Common @@ -194,10 +205,18 @@ func (d groupPerfCounterInfo) Len() int { func (d groupPerfCounterInfo) Less(i, j int) bool { ci := d.ids[i].CounterId cj := d.ids[j].CounterId - gi := d.info[ci].GroupInfo.GetElementDescription() - gj := d.info[cj].GroupInfo.GetElementDescription() - return gi.Key < gj.Key + giKey := "-" + gjKey := "-" + + if gi, ok := d.info[ci]; ok { + giKey = gi.GroupInfo.GetElementDescription().Key + } + if gj, ok := d.info[cj]; ok { + gjKey = gj.GroupInfo.GetElementDescription().Key + } + + return giKey < gjKey } func (d groupPerfCounterInfo) Swap(i, j int) { @@ -260,6 +279,21 @@ func (m *Manager) Query(ctx context.Context, spec []types.PerfQuerySpec) ([]type return res.Returnval, nil } +// QueryCounter wraps the QueryPerfCounter method. +func (m *Manager) QueryCounter(ctx context.Context, ids []int32) ([]types.PerfCounterInfo, error) { + req := types.QueryPerfCounter{ + This: m.Reference(), + CounterId: ids, + } + + res, err := methods.QueryPerfCounter(ctx, m.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + // SampleByName uses the spec param as a template, constructing a []types.PerfQuerySpec for the given metrics and entities // and invoking the Query method. // The spec template can specify instances using the MetricId.Instance field, by default all instances are collected. @@ -297,7 +331,10 @@ func (m *Manager) SampleByName(ctx context.Context, spec types.PerfQuerySpec, me spec.MaxSample = 1 } + truncate := false + if spec.IntervalId >= 60 && spec.StartTime == nil { + truncate = true // Need a StartTime to make use of history now, err := methods.GetCurrentTime(ctx, m.Client()) if err != nil { @@ -305,7 +342,7 @@ func (m *Manager) SampleByName(ctx context.Context, spec types.PerfQuerySpec, me } // Go back in time - x := spec.IntervalId * -1 * spec.MaxSample + x := spec.IntervalId * -1 * (spec.MaxSample * 2) t := now.Add(time.Duration(x) * time.Second) spec.StartTime = &t } @@ -317,15 +354,51 @@ func (m *Manager) SampleByName(ctx context.Context, spec types.PerfQuerySpec, me query = append(query, spec) } - return m.Query(ctx, query) + series, err := m.Query(ctx, query) + if err != nil { + return nil, err + } + + if truncate { + // Going back in time with IntervalId * MaxSample isn't always far enough, + // depending on when the historical data is saved in vCenter. + // So we go back twice as far and truncate here if needed. + for i := range series { + s, ok := series[i].(*types.PerfEntityMetric) + if !ok { + break + } + + n := len(s.SampleInfo) + diff := n - int(spec.MaxSample) + if diff > 0 { + s.SampleInfo = s.SampleInfo[diff:] + } + + for j := range s.Value { + v, ok := s.Value[j].(*types.PerfMetricIntSeries) + if !ok { + break + } + + n = len(v.Value) + diff = n - int(spec.MaxSample) + if diff > 0 { + v.Value = v.Value[diff:] + } + } + } + } + + return series, nil } // MetricSeries contains the same data as types.PerfMetricIntSeries, but with the CounterId converted to Name. type MetricSeries struct { - Name string + Name string `json:"name"` unit string - Instance string - Value []int64 + Instance string `json:"instance"` + Value []int64 `json:"value"` } func (s *MetricSeries) Format(val int64) string { @@ -350,10 +423,10 @@ func (s *MetricSeries) ValueCSV() string { // EntityMetric contains the same data as types.PerfEntityMetric, but with MetricSeries type for the Value field. type EntityMetric struct { - Entity types.ManagedObjectReference + Entity types.ManagedObjectReference `json:"entity"` - SampleInfo []types.PerfSampleInfo - Value []MetricSeries + SampleInfo []types.PerfSampleInfo `json:"sampleInfo"` + Value []MetricSeries `json:"value"` } // SampleInfoCSV converts the SampleInfo field to a CSV string @@ -390,10 +463,14 @@ func (m *Manager) ToMetricSeries(ctx context.Context, series []types.BasePerfEnt for j := range s.Value { v := s.Value[j].(*types.PerfMetricIntSeries) + info, ok := counters[v.Id.CounterId] + if !ok { + continue + } values = append(values, MetricSeries{ - Name: counters[v.Id.CounterId].Name(), - unit: counters[v.Id.CounterId].UnitInfo.GetElementDescription().Key, + Name: info.Name(), + unit: info.UnitInfo.GetElementDescription().Key, Instance: v.Id.Instance, Value: v.Value, }) diff --git a/vendor/github.com/vmware/govmomi/program.mk b/vendor/github.com/vmware/govmomi/program.mk index 9c6996aeab..f24939934f 100644 --- a/vendor/github.com/vmware/govmomi/program.mk +++ b/vendor/github.com/vmware/govmomi/program.mk @@ -1,3 +1,6 @@ +# Copyright (c) 2021 VMware, Inc. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + ifneq (,$(strip $(GOOS))) ifeq (,$(strip $(GOARCH))) GOARCH := $(shell go env | grep GOARCH | awk -F= '{print $$2}' | tr -d '"') @@ -30,7 +33,7 @@ $(PROGRAM): CGO_ENABLED=0 go build -a $(BUILD_ARGS) -o $@ install: - CGO_ENABLED=0 go install $(BUILD_ARGS) + CGO_ENABLED=0 go install -v $(BUILD_ARGS) ifneq (,$(strip $(BUILD_OS))) ifneq (,$(strip $(BUILD_ARCH))) diff --git a/vendor/github.com/vmware/govmomi/property/collector.go b/vendor/github.com/vmware/govmomi/property/collector.go index b77e600611..263621a06a 100644 --- a/vendor/github.com/vmware/govmomi/property/collector.go +++ b/vendor/github.com/vmware/govmomi/property/collector.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2024 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 +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, @@ -19,6 +19,8 @@ package property import ( "context" "errors" + "fmt" + "sync" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" @@ -27,12 +29,19 @@ import ( "github.com/vmware/govmomi/vim25/types" ) +// ErrConcurrentCollector is returned from WaitForUpdates, WaitForUpdatesEx, +// or CheckForUpdates if any of those calls are unable to obtain an exclusive +// lock for the property collector. +var ErrConcurrentCollector = fmt.Errorf( + "only one goroutine may invoke WaitForUpdates, WaitForUpdatesEx, " + + "or CheckForUpdates on a given PropertyCollector") + // Collector models the PropertyCollector managed object. // // For more information, see: // http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvmodl.query.PropertyCollector.html -// type Collector struct { + mu sync.Mutex roundTripper soap.RoundTripper reference types.ManagedObjectReference } @@ -47,7 +56,7 @@ func DefaultCollector(c *vim25.Client) *Collector { return &p } -func (p Collector) Reference() types.ManagedObjectReference { +func (p *Collector) Reference() types.ManagedObjectReference { return p.reference } @@ -86,21 +95,37 @@ func (p *Collector) Destroy(ctx context.Context) error { return nil } -func (p *Collector) CreateFilter(ctx context.Context, req types.CreateFilter) error { +func (p *Collector) CreateFilter(ctx context.Context, req types.CreateFilter) (*Filter, error) { req.This = p.Reference() - _, err := methods.CreateFilter(ctx, p.roundTripper, &req) + resp, err := methods.CreateFilter(ctx, p.roundTripper, &req) if err != nil { - return err + return nil, err } - return nil + return &Filter{roundTripper: p.roundTripper, reference: resp.Returnval}, nil } -func (p *Collector) WaitForUpdates(ctx context.Context, v string) (*types.UpdateSet, error) { +// Deprecated: Please use WaitForUpdatesEx instead. +func (p *Collector) WaitForUpdates( + ctx context.Context, + version string, + opts ...*types.WaitOptions) (*types.UpdateSet, error) { + + if !p.mu.TryLock() { + return nil, ErrConcurrentCollector + } + defer p.mu.Unlock() + req := types.WaitForUpdatesEx{ This: p.Reference(), - Version: v, + Version: version, + } + + if len(opts) == 1 { + req.Options = opts[0] + } else if len(opts) > 1 { + panic("only one option may be specified") } res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req) @@ -117,9 +142,29 @@ func (p *Collector) CancelWaitForUpdates(ctx context.Context) error { return err } -func (p *Collector) RetrieveProperties(ctx context.Context, req types.RetrieveProperties) (*types.RetrievePropertiesResponse, error) { - req.This = p.Reference() - return methods.RetrieveProperties(ctx, p.roundTripper, &req) +// RetrieveProperties wraps RetrievePropertiesEx and ContinueRetrievePropertiesEx to collect properties in batches. +func (p *Collector) RetrieveProperties( + ctx context.Context, + req types.RetrieveProperties, + maxObjectsArgs ...int32) (*types.RetrievePropertiesResponse, error) { + + var opts types.RetrieveOptions + if l := len(maxObjectsArgs); l > 1 { + return nil, fmt.Errorf("maxObjectsArgs accepts a single value") + } else if l == 1 { + opts.MaxObjects = maxObjectsArgs[0] + } + + objects, err := mo.RetrievePropertiesEx(ctx, p.roundTripper, types.RetrievePropertiesEx{ + This: p.Reference(), + SpecSet: req.SpecSet, + Options: opts, + }) + if err != nil { + return nil, err + } + + return &types.RetrievePropertiesResponse{Returnval: objects}, nil } // Retrieve loads properties for a slice of managed objects. The dst argument @@ -143,7 +188,7 @@ func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectRefe spec := types.PropertySpec{ Type: obj.Type, } - if ps == nil { + if len(ps) == 0 { spec.All = types.NewBool(true) } else { spec.PathSet = ps @@ -179,11 +224,18 @@ func (p *Collector) Retrieve(ctx context.Context, objs []types.ManagedObjectRefe return nil } - return mo.LoadRetrievePropertiesResponse(res, dst) + return mo.LoadObjectContent(res.Returnval, dst) } -// RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter. -func (p *Collector) RetrieveWithFilter(ctx context.Context, objs []types.ManagedObjectReference, ps []string, dst interface{}, filter Filter) error { +// RetrieveWithFilter populates dst as Retrieve does, but only for entities +// that match the specified filter. +func (p *Collector) RetrieveWithFilter( + ctx context.Context, + objs []types.ManagedObjectReference, + ps []string, + dst interface{}, + filter Match) error { + if len(filter) == 0 { return p.Retrieve(ctx, objs, ps, dst) } @@ -195,7 +247,7 @@ func (p *Collector) RetrieveWithFilter(ctx context.Context, objs []types.Managed return err } - objs = filter.MatchObjectContent(content) + objs = filter.ObjectContent(content) if len(objs) == 0 { return nil @@ -209,3 +261,71 @@ func (p *Collector) RetrieveOne(ctx context.Context, obj types.ManagedObjectRefe var objs = []types.ManagedObjectReference{obj} return p.Retrieve(ctx, objs, ps, dst) } + +// WaitForUpdatesEx waits for any of the specified properties of the specified +// managed object to change. It calls the specified function for every update it +// receives. If this function returns false, it continues waiting for +// subsequent updates. If this function returns true, it stops waiting and +// returns. +// +// If the Context is canceled, a call to CancelWaitForUpdates() is made and its +// error value is returned. +// +// By default, ObjectUpdate.MissingSet faults are not propagated to the returned +// error, set WaitFilter.PropagateMissing=true to enable MissingSet fault +// propagation. +func (p *Collector) WaitForUpdatesEx( + ctx context.Context, + opts WaitOptions, + onUpdatesFn func([]types.ObjectUpdate) bool) error { + + if !p.mu.TryLock() { + return ErrConcurrentCollector + } + defer p.mu.Unlock() + + req := types.WaitForUpdatesEx{ + This: p.Reference(), + Options: opts.Options, + } + + for { + res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req) + if err != nil { + if ctx.Err() == context.Canceled { + return p.CancelWaitForUpdates(context.Background()) + } + return err + } + + set := res.Returnval + if set == nil { + if req.Options != nil && req.Options.MaxWaitSeconds != nil { + return nil // WaitOptions.MaxWaitSeconds exceeded + } + // Retry if the result came back empty + continue + } + + req.Version = set.Version + opts.Truncated = false + if set.Truncated != nil { + opts.Truncated = *set.Truncated + } + + for _, fs := range set.FilterSet { + if opts.PropagateMissing { + for i := range fs.ObjectSet { + for _, p := range fs.ObjectSet[i].MissingSet { + // Same behavior as mo.ObjectContentToType() + return soap.WrapVimFault(p.Fault.Fault) + } + } + } + + if onUpdatesFn(fs.ObjectSet) { + return nil + } + } + } +} diff --git a/vendor/github.com/vmware/govmomi/property/filter.go b/vendor/github.com/vmware/govmomi/property/filter.go index a4bf16d055..40cd718fad 100644 --- a/vendor/github.com/vmware/govmomi/property/filter.go +++ b/vendor/github.com/vmware/govmomi/property/filter.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2024 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. @@ -17,123 +17,38 @@ limitations under the License. package property import ( - "fmt" - "path" - "reflect" - "strconv" - "strings" + "context" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" ) -// Filter provides methods for matching against types.DynamicProperty -type Filter map[string]types.AnyType - -// Keys returns the Filter map keys as a []string -func (f Filter) Keys() []string { - keys := make([]string, 0, len(f)) - - for key := range f { - keys = append(keys, key) - } - - return keys +// Filter models the Filter managed object. +// +// For more information, see: +// https://vdc-download.vmware.com/vmwb-repository/dcr-public/184bb3ba-6fa8-4574-a767-d0c96e2a38f4/ba9422ef-405c-47dd-8553-e11b619185b2/SDK/vsphere-ws/docs/ReferenceGuide/vmodl.query.PropertyCollector.Filter.html. +type Filter struct { + roundTripper soap.RoundTripper + reference types.ManagedObjectReference } -// MatchProperty returns true if a Filter entry matches the given prop. -func (f Filter) MatchProperty(prop types.DynamicProperty) bool { - match, ok := f[prop.Name] - if !ok { - return false - } - - if match == prop.Val { - return true - } - - ptype := reflect.TypeOf(prop.Val) - - if strings.HasPrefix(ptype.Name(), "ArrayOf") { - pval := reflect.ValueOf(prop.Val).Field(0) - - for i := 0; i < pval.Len(); i++ { - prop.Val = pval.Index(i).Interface() - - if f.MatchProperty(prop) { - return true - } - } - - return false - } - - if reflect.TypeOf(match) != ptype { - s, ok := match.(string) - if !ok { - return false - } - - // convert if we can - switch prop.Val.(type) { - case bool: - match, _ = strconv.ParseBool(s) - case int16: - x, _ := strconv.ParseInt(s, 10, 16) - match = int16(x) - case int32: - x, _ := strconv.ParseInt(s, 10, 32) - match = int32(x) - case int64: - match, _ = strconv.ParseInt(s, 10, 64) - case float32: - x, _ := strconv.ParseFloat(s, 32) - match = float32(x) - case float64: - match, _ = strconv.ParseFloat(s, 64) - case fmt.Stringer: - prop.Val = prop.Val.(fmt.Stringer).String() - default: - if ptype.Kind() != reflect.String { - return false - } - // An enum type we can convert to a string type - prop.Val = reflect.ValueOf(prop.Val).String() - } - } - - switch pval := prop.Val.(type) { - case string: - s := match.(string) - if s == "*" { - return true // TODO: path.Match fails if s contains a '/' - } - m, _ := path.Match(s, pval) - return m - default: - return reflect.DeepEqual(match, pval) - } +func (f Filter) Reference() types.ManagedObjectReference { + return f.reference } -// MatchPropertyList returns true if all given props match the Filter. -func (f Filter) MatchPropertyList(props []types.DynamicProperty) bool { - for _, p := range props { - if !f.MatchProperty(p) { - return false - } +// Destroy destroys this filter. +// +// This operation can be called explicitly, or it can take place implicitly when +// the session that created the filter is closed. +func (f *Filter) Destroy(ctx context.Context) error { + if _, err := methods.DestroyPropertyFilter( + ctx, + f.roundTripper, + &types.DestroyPropertyFilter{This: f.Reference()}); err != nil { + + return err } - - return len(f) == len(props) // false if a property such as VM "guest" is unset -} - -// MatchObjectContent returns a list of ObjectContent.Obj where the ObjectContent.PropSet matches the Filter. -func (f Filter) MatchObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference { - var refs []types.ManagedObjectReference - - for _, o := range objects { - if f.MatchPropertyList(o.PropSet) { - refs = append(refs, o.Obj) - } - } - - return refs + f.reference = types.ManagedObjectReference{} + return nil } diff --git a/vendor/github.com/vmware/govmomi/property/match.go b/vendor/github.com/vmware/govmomi/property/match.go new file mode 100644 index 0000000000..f3922296b9 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/property/match.go @@ -0,0 +1,170 @@ +/* +Copyright (c) 2017-2024 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 property + +import ( + "fmt" + "path" + "reflect" + "strconv" + "strings" + + "github.com/vmware/govmomi/vim25/types" +) + +// Match provides methods for matching against types.DynamicProperty +type Match map[string]types.AnyType + +// Keys returns the Match map keys as a []string +func (m Match) Keys() []string { + keys := make([]string, 0, len(m)) + + for key := range m { + keys = append(keys, key) + } + + return keys +} + +// Property returns true if an entry matches the given prop. +func (m Match) Property(prop types.DynamicProperty) bool { + if prop.Val == nil { + return false + } + match, ok := m[prop.Name] + if !ok { + return false + } + + if match == prop.Val { + return true + } + + ptype := reflect.TypeOf(prop.Val) + + if strings.HasPrefix(ptype.Name(), "ArrayOf") { + pval := reflect.ValueOf(prop.Val).Field(0) + + for i := 0; i < pval.Len(); i++ { + prop.Val = pval.Index(i).Interface() + + if m.Property(prop) { + return true + } + } + + return false + } + + if reflect.TypeOf(match) != ptype { + s, ok := match.(string) + if !ok { + return false + } + + // convert if we can + switch val := prop.Val.(type) { + case bool: + match, _ = strconv.ParseBool(s) + case int16: + x, _ := strconv.ParseInt(s, 10, 16) + match = int16(x) + case int32: + x, _ := strconv.ParseInt(s, 10, 32) + match = int32(x) + case int64: + match, _ = strconv.ParseInt(s, 10, 64) + case float32: + x, _ := strconv.ParseFloat(s, 32) + match = float32(x) + case float64: + match, _ = strconv.ParseFloat(s, 64) + case fmt.Stringer: + prop.Val = val.String() + case *types.CustomFieldStringValue: + prop.Val = fmt.Sprintf("%d:%s", val.Key, val.Value) + default: + if ptype.Kind() != reflect.String { + return false + } + // An enum type we can convert to a string type + prop.Val = reflect.ValueOf(prop.Val).String() + } + } + + switch pval := prop.Val.(type) { + case string: + s := match.(string) + if s == "*" { + return true // TODO: path.Match fails if s contains a '/' + } + m, _ := path.Match(s, pval) + return m + default: + return reflect.DeepEqual(match, pval) + } +} + +// List returns true if all given props match. +func (m Match) List(props []types.DynamicProperty) bool { + for _, p := range props { + if !m.Property(p) { + return false + } + } + + return len(m) == len(props) // false if a property such as VM "guest" is unset +} + +// ObjectContent returns a list of ObjectContent.Obj where the +// ObjectContent.PropSet matches all properties the Filter. +func (m Match) ObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference { + var refs []types.ManagedObjectReference + + for _, o := range objects { + if m.List(o.PropSet) { + refs = append(refs, o.Obj) + } + } + + return refs +} + +// AnyList returns true if any given props match. +func (m Match) AnyList(props []types.DynamicProperty) bool { + for _, p := range props { + if m.Property(p) { + return true + } + } + + return false +} + +// AnyObjectContent returns a list of ObjectContent.Obj where the +// ObjectContent.PropSet matches any property. +func (m Match) AnyObjectContent(objects []types.ObjectContent) []types.ManagedObjectReference { + var refs []types.ManagedObjectReference + + for _, o := range objects { + if m.AnyList(o.PropSet) { + refs = append(refs, o.Obj) + } + } + + return refs +} diff --git a/vendor/github.com/vmware/govmomi/property/wait.go b/vendor/github.com/vmware/govmomi/property/wait.go index f730525ca7..07ea3cb5dc 100644 --- a/vendor/github.com/vmware/govmomi/property/wait.go +++ b/vendor/github.com/vmware/govmomi/property/wait.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2024 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. @@ -18,15 +18,23 @@ package property import ( "context" + "fmt" - "github.com/vmware/govmomi/vim25/methods" "github.com/vmware/govmomi/vim25/types" ) +// WaitOptions defines options for a property collector's WaitForUpdatesEx +// method. +type WaitOptions struct { + Options *types.WaitOptions + PropagateMissing bool + Truncated bool +} + // WaitFilter provides helpers to construct a types.CreateFilter for use with property.Wait type WaitFilter struct { types.CreateFilter - Options *types.WaitOptions + WaitOptions } // Add a new ObjectSpec and PropertySpec to the WaitFilter @@ -67,8 +75,8 @@ func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, p }) } -// WaitForUpdates waits for any of the specified properties of the specified managed -// object to change. It calls the specified function for every update it +// WaitForUpdates waits for any of the specified properties of the specified +// managed object to change. It calls the specified function for every update it // receives. If this function returns false, it continues waiting for // subsequent updates. If this function returns true, it stops waiting and // returns. @@ -77,55 +85,86 @@ func Wait(ctx context.Context, c *Collector, obj types.ManagedObjectReference, p // creates a new property collector and calls CreateFilter. A new property // collector is required because filters can only be added, not removed. // -// If the Context is canceled, a call to CancelWaitForUpdates() is made and its error value is returned. -// The newly created collector is destroyed before this function returns (both -// in case of success or error). +// If the Context is canceled, a call to CancelWaitForUpdates() is made and its +// error value is returned. The newly created collector is destroyed before this +// function returns (both in case of success or error). // -func WaitForUpdates(ctx context.Context, c *Collector, filter *WaitFilter, f func([]types.ObjectUpdate) bool) error { - p, err := c.Create(ctx) +// By default, ObjectUpdate.MissingSet faults are not propagated to the returned +// error, set WaitFilter.PropagateMissing=true to enable MissingSet fault +// propagation. +func WaitForUpdates( + ctx context.Context, + c *Collector, + filter *WaitFilter, + onUpdatesFn func([]types.ObjectUpdate) bool) (result error) { + + pc, err := c.Create(ctx) if err != nil { return err } // Attempt to destroy the collector using the background context, as the // specified context may have timed out or have been canceled. - defer p.Destroy(context.Background()) + defer func() { + if err := pc.Destroy(context.Background()); err != nil { + if result == nil { + result = err + } else { + result = fmt.Errorf( + "destroy property collector failed with %s after failing to wait for updates: %w", + err, + result) + } + } + }() - err = p.CreateFilter(ctx, filter.CreateFilter) + // Create a property filter for the property collector. + if _, err := pc.CreateFilter(ctx, filter.CreateFilter); err != nil { + return err + } + + return pc.WaitForUpdatesEx(ctx, filter.WaitOptions, onUpdatesFn) +} + +// WaitForUpdates waits for any of the specified properties of the specified +// managed object to change. It calls the specified function for every update it +// receives. If this function returns false, it continues waiting for +// subsequent updates. If this function returns true, it stops waiting and +// returns. +// +// If the Context is canceled, a call to CancelWaitForUpdates() is made and its +// error value is returned. +// +// By default, ObjectUpdate.MissingSet faults are not propagated to the returned +// error, set WaitFilter.PropagateMissing=true to enable MissingSet fault +// propagation. +func WaitForUpdatesEx( + ctx context.Context, + pc *Collector, + filter *WaitFilter, + onUpdatesFn func([]types.ObjectUpdate) bool) (result error) { + + // Create a property filter for the property collector. + pf, err := pc.CreateFilter(ctx, filter.CreateFilter) if err != nil { return err } - req := types.WaitForUpdatesEx{ - This: p.Reference(), - Options: filter.Options, - } - - for { - res, err := methods.WaitForUpdatesEx(ctx, p.roundTripper, &req) - if err != nil { - if ctx.Err() == context.Canceled { - werr := p.CancelWaitForUpdates(context.Background()) - return werr - } - return err - } - - set := res.Returnval - if set == nil { - if req.Options != nil && req.Options.MaxWaitSeconds != nil { - return nil // WaitOptions.MaxWaitSeconds exceeded - } - // Retry if the result came back empty - continue - } - - req.Version = set.Version - - for _, fs := range set.FilterSet { - if f(fs.ObjectSet) { - return nil + // Destroy the filter using the background context, as the specified context + // may have timed out or have been canceled. + defer func() { + if err := pf.Destroy(context.Background()); err != nil { + if result == nil { + result = err + } else { + result = fmt.Errorf( + "destroy property filter failed with %s after failing to wait for updates: %w", + err, + result) } } - } + + }() + + return pc.WaitForUpdatesEx(ctx, filter.WaitOptions, onUpdatesFn) } diff --git a/vendor/github.com/vmware/govmomi/session/keep_alive.go b/vendor/github.com/vmware/govmomi/session/keep_alive.go index 3b44f5ffb6..7c1bebf913 100644 --- a/vendor/github.com/vmware/govmomi/session/keep_alive.go +++ b/vendor/github.com/vmware/govmomi/session/keep_alive.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2020 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. @@ -17,110 +17,24 @@ limitations under the License. package session import ( - "context" - "sync" "time" - "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/session/keepalive" "github.com/vmware/govmomi/vim25/soap" ) -type keepAlive struct { - sync.Mutex - - roundTripper soap.RoundTripper - idleTime time.Duration - notifyRequest chan struct{} - notifyStop chan struct{} - notifyWaitGroup sync.WaitGroup - - // keepAlive executes a request in the background with the purpose of - // keeping the session active. The response for this request is discarded. - keepAlive func(soap.RoundTripper) error -} - -func defaultKeepAlive(roundTripper soap.RoundTripper) error { - _, _ = methods.GetCurrentTime(context.Background(), roundTripper) - return nil -} - -// KeepAlive wraps the specified soap.RoundTripper and executes a meaningless -// API request in the background after the RoundTripper has been idle for the -// specified amount of idle time. The keep alive process only starts once a -// user logs in and runs until the user logs out again. +// KeepAlive is a backward compatible wrapper around KeepAliveHandler. func KeepAlive(roundTripper soap.RoundTripper, idleTime time.Duration) soap.RoundTripper { - return KeepAliveHandler(roundTripper, idleTime, defaultKeepAlive) + return KeepAliveHandler(roundTripper, idleTime, nil) } -// KeepAliveHandler works as KeepAlive() does, but the handler param can decide how to handle errors. -// For example, if connectivity to ESX/VC is down long enough for a session to expire, a handler can choose to -// Login() on a types.NotAuthenticated error. If handler returns non-nil, the keep alive go routine will be stopped. +// KeepAliveHandler is a backward compatible wrapper around keepalive.NewHandlerSOAP. func KeepAliveHandler(roundTripper soap.RoundTripper, idleTime time.Duration, handler func(soap.RoundTripper) error) soap.RoundTripper { - k := &keepAlive{ - roundTripper: roundTripper, - idleTime: idleTime, - notifyRequest: make(chan struct{}), - } - - k.keepAlive = handler - - return k -} - -func (k *keepAlive) start() { - k.Lock() - defer k.Unlock() - - if k.notifyStop != nil { - return - } - - // This channel must be closed to terminate idle timer. - k.notifyStop = make(chan struct{}) - k.notifyWaitGroup.Add(1) - - go func() { - defer k.notifyWaitGroup.Done() - - for t := time.NewTimer(k.idleTime); ; { - select { - case <-k.notifyStop: - return - case <-k.notifyRequest: - t.Reset(k.idleTime) - case <-t.C: - if err := k.keepAlive(k.roundTripper); err != nil { - k.stop() - } - t = time.NewTimer(k.idleTime) - } + var f func() error + if handler != nil { + f = func() error { + return handler(roundTripper) } - }() -} - -func (k *keepAlive) stop() { - k.Lock() - defer k.Unlock() - - if k.notifyStop != nil { - close(k.notifyStop) - k.notifyWaitGroup.Wait() - k.notifyStop = nil } -} - -func (k *keepAlive) RoundTrip(ctx context.Context, req, res soap.HasFault) error { - err := k.roundTripper.RoundTrip(ctx, req, res) - if err != nil { - return err - } - // Start ticker on login, stop ticker on logout. - switch req.(type) { - case *methods.LoginBody, *methods.LoginExtensionByCertificateBody, *methods.LoginByTokenBody: - k.start() - case *methods.LogoutBody: - k.stop() - } - - return nil + return keepalive.NewHandlerSOAP(roundTripper, idleTime, f) } diff --git a/vendor/github.com/vmware/govmomi/session/keepalive/handler.go b/vendor/github.com/vmware/govmomi/session/keepalive/handler.go new file mode 100644 index 0000000000..3ebf046a53 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/session/keepalive/handler.go @@ -0,0 +1,204 @@ +/* +Copyright (c) 2020 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 keepalive + +import ( + "context" + "errors" + "net/http" + "sync" + "time" + + "github.com/vmware/govmomi/vapi/rest" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" +) + +// handler contains the generic keep alive settings and logic +type handler struct { + mu sync.Mutex + notifyStop chan struct{} + notifyWaitGroup sync.WaitGroup + + idle time.Duration + send func() error +} + +// NewHandlerSOAP returns a soap.RoundTripper for use with a vim25.Client +// The idle time specifies the interval in between send() requests. Defaults to 10 minutes. +// The send func is used to keep a session alive. Defaults to calling vim25 GetCurrentTime(). +// The keep alive goroutine starts when a Login method is called and runs until Logout is called or send returns an error. +func NewHandlerSOAP(c soap.RoundTripper, idle time.Duration, send func() error) *HandlerSOAP { + h := &handler{ + idle: idle, + send: send, + } + + if send == nil { + h.send = func() error { + return h.keepAliveSOAP(c) + } + } + + return &HandlerSOAP{h, c} +} + +// NewHandlerREST returns an http.RoundTripper for use with a rest.Client +// The idle time specifies the interval in between send() requests. Defaults to 10 minutes. +// The send func is used to keep a session alive. Defaults to calling the rest.Client.Session() method +// The keep alive goroutine starts when a Login method is called and runs until Logout is called or send returns an error. +func NewHandlerREST(c *rest.Client, idle time.Duration, send func() error) *HandlerREST { + h := &handler{ + idle: idle, + send: send, + } + + if send == nil { + h.send = func() error { + return h.keepAliveREST(c) + } + } + + return &HandlerREST{h, c.Transport} +} + +func (h *handler) keepAliveSOAP(rt soap.RoundTripper) error { + ctx := context.Background() + _, err := methods.GetCurrentTime(ctx, rt) + return err +} + +func (h *handler) keepAliveREST(c *rest.Client) error { + ctx := context.Background() + + s, err := c.Session(ctx) + if err != nil { + return err + } + if s != nil { + return nil + } + return errors.New(http.StatusText(http.StatusUnauthorized)) +} + +// Start explicitly starts the keep alive go routine. +// For use with session cache.Client, as cached sessions may not involve Login/Logout via RoundTripper. +func (h *handler) Start() { + h.mu.Lock() + defer h.mu.Unlock() + + if h.notifyStop != nil { + return + } + + if h.idle == 0 { + h.idle = time.Minute * 10 + } + + // This channel must be closed to terminate idle timer. + h.notifyStop = make(chan struct{}) + h.notifyWaitGroup.Add(1) + + go func() { + for t := time.NewTimer(h.idle); ; { + select { + case <-h.notifyStop: + h.notifyWaitGroup.Done() + t.Stop() + return + case <-t.C: + if err := h.send(); err != nil { + h.notifyWaitGroup.Done() + h.Stop() + return + } + t.Reset(h.idle) + } + } + }() +} + +// Stop explicitly stops the keep alive go routine. +// For use with session cache.Client, as cached sessions may not involve Login/Logout via RoundTripper. +func (h *handler) Stop() { + h.mu.Lock() + defer h.mu.Unlock() + + if h.notifyStop != nil { + close(h.notifyStop) + h.notifyWaitGroup.Wait() + h.notifyStop = nil + } +} + +// HandlerSOAP is a keep alive implementation for use with vim25.Client +type HandlerSOAP struct { + *handler + + roundTripper soap.RoundTripper +} + +// RoundTrip implements soap.RoundTripper +func (h *HandlerSOAP) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + // Stop ticker on logout. + switch req.(type) { + case *methods.LogoutBody: + h.Stop() + } + + err := h.roundTripper.RoundTrip(ctx, req, res) + if err != nil { + return err + } + + // Start ticker on login. + switch req.(type) { + case *methods.LoginBody, *methods.LoginExtensionByCertificateBody, *methods.LoginByTokenBody: + h.Start() + } + + return nil +} + +// HandlerREST is a keep alive implementation for use with rest.Client +type HandlerREST struct { + *handler + + roundTripper http.RoundTripper +} + +// RoundTrip implements http.RoundTripper +func (h *HandlerREST) RoundTrip(req *http.Request) (*http.Response, error) { + if req.URL.Path != "/rest/com/vmware/cis/session" { + return h.roundTripper.RoundTrip(req) + } + + if req.Method == http.MethodDelete { // Logout + h.Stop() + } + + res, err := h.roundTripper.RoundTrip(req) + if err != nil { + return res, err + } + + if req.Method == http.MethodPost { // Login + h.Start() + } + + return res, err +} diff --git a/vendor/github.com/vmware/govmomi/session/manager.go b/vendor/github.com/vmware/govmomi/session/manager.go index ad3219716a..e2d70a2f60 100644 --- a/vendor/github.com/vmware/govmomi/session/manager.go +++ b/vendor/github.com/vmware/govmomi/session/manager.go @@ -18,9 +18,9 @@ package session import ( "context" - "net/http" "net/url" "os" + "strings" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/vim25" @@ -41,6 +41,21 @@ func init() { } } +// Secret returns the contents if a file path value is given, otherwise returns value itself. +func Secret(value string) (string, error) { + if len(value) == 0 { + return value, nil + } + contents, err := os.ReadFile(value) + if err != nil { + if os.IsPermission(err) { + return "", err + } + return value, nil + } + return strings.TrimSpace(string(contents)), nil +} + type Manager struct { client *vim25.Client userSession *types.UserSession @@ -107,7 +122,7 @@ func (sm *Manager) LoginExtensionByCertificate(ctx context.Context, key string) // "Post https://sdkTunnel:8089/sdk: x509: certificate is valid for $vcenter_hostname, not sdkTunnel" // The only easy way around this is to disable verification for the call to LoginExtensionByCertificate(). // TODO: find a way to avoid disabling InsecureSkipVerify. - c.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify = true + c.DefaultTransport().TLSClientConfig.InsecureSkipVerify = true } req := types.LoginExtensionByCertificate{ @@ -265,3 +280,14 @@ func (sm *Manager) CloneSession(ctx context.Context, ticket string) error { sm.userSession = &res.Returnval return nil } + +func (sm *Manager) UpdateServiceMessage(ctx context.Context, message string) error { + req := types.UpdateServiceMessage{ + This: sm.Reference(), + Message: message, + } + + _, err := methods.UpdateServiceMessage(ctx, sm.client, &req) + + return err +} diff --git a/vendor/github.com/vmware/govmomi/task/error.go b/vendor/github.com/vmware/govmomi/task/error.go index 5f6b8503f5..3fff5aa265 100644 --- a/vendor/github.com/vmware/govmomi/task/error.go +++ b/vendor/github.com/vmware/govmomi/task/error.go @@ -20,6 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" type Error struct { *types.LocalizedMethodFault + Description *types.LocalizableMessage } // Error returns the task's localized fault message. diff --git a/vendor/github.com/vmware/govmomi/task/history_collector.go b/vendor/github.com/vmware/govmomi/task/history_collector.go new file mode 100644 index 0000000000..7d8a6cf04a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/task/history_collector.go @@ -0,0 +1,89 @@ +/* +Copyright (c) 2015-2022 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 task + +import ( + "context" + + "github.com/vmware/govmomi/history" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" +) + +// HistoryCollector provides a mechanism for retrieving historical data and +// updates when the server appends new tasks. +type HistoryCollector struct { + *history.Collector +} + +func newHistoryCollector(c *vim25.Client, ref types.ManagedObjectReference) *HistoryCollector { + return &HistoryCollector{ + Collector: history.NewCollector(c, ref), + } +} + +// LatestPage returns items in the 'viewable latest page' of the task history collector. +// As new tasks that match the collector's TaskFilterSpec are created, +// they are added to this page, and the oldest tasks are removed from the collector to keep +// the size of the page to that allowed by SetCollectorPageSize. +// The "oldest task" is the one with the oldest creation time. The tasks in the returned page are unordered. +func (h HistoryCollector) LatestPage(ctx context.Context) ([]types.TaskInfo, error) { + var o mo.TaskHistoryCollector + + err := h.Properties(ctx, h.Reference(), []string{"latestPage"}, &o) + if err != nil { + return nil, err + } + + return o.LatestPage, nil +} + +// ReadNextTasks reads the scrollable view from the current position. The +// scrollable position is moved to the next newer page after the read. No item +// is returned when the end of the collector is reached. +func (h HistoryCollector) ReadNextTasks(ctx context.Context, maxCount int32) ([]types.TaskInfo, error) { + req := types.ReadNextTasks{ + This: h.Reference(), + MaxCount: maxCount, + } + + res, err := methods.ReadNextTasks(ctx, h.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +// ReadPreviousTasks reads the scrollable view from the current position. The +// scrollable position is then moved to the next older page after the read. No +// item is returned when the head of the collector is reached. +func (h HistoryCollector) ReadPreviousTasks(ctx context.Context, maxCount int32) ([]types.TaskInfo, error) { + req := types.ReadPreviousTasks{ + This: h.Reference(), + MaxCount: maxCount, + } + + res, err := methods.ReadPreviousTasks(ctx, h.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/task/manager.go b/vendor/github.com/vmware/govmomi/task/manager.go new file mode 100644 index 0000000000..8279089d7d --- /dev/null +++ b/vendor/github.com/vmware/govmomi/task/manager.go @@ -0,0 +1,61 @@ +/* +Copyright (c) 2014-2022 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 task + +import ( + "context" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +type Manager struct { + r types.ManagedObjectReference + c *vim25.Client +} + +// NewManager creates a new task manager +func NewManager(c *vim25.Client) *Manager { + m := Manager{ + r: *c.ServiceContent.TaskManager, + c: c, + } + + return &m +} + +// Reference returns the task.Manager MOID +func (m Manager) Reference() types.ManagedObjectReference { + return m.r +} + +// CreateCollectorForTasks returns a task history collector, a specialized +// history collector that gathers TaskInfo data objects. +func (m Manager) CreateCollectorForTasks(ctx context.Context, filter types.TaskFilterSpec) (*HistoryCollector, error) { + req := types.CreateCollectorForTasks{ + This: m.r, + Filter: filter, + } + + res, err := methods.CreateCollectorForTasks(ctx, m.c, &req) + if err != nil { + return nil, err + } + + return newHistoryCollector(m.c, res.Returnval), nil +} diff --git a/vendor/github.com/vmware/govmomi/task/wait.go b/vendor/github.com/vmware/govmomi/task/wait.go index 19fee53846..8f3a2fe6b0 100644 --- a/vendor/github.com/vmware/govmomi/task/wait.go +++ b/vendor/github.com/vmware/govmomi/task/wait.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2024 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 +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, @@ -38,7 +38,7 @@ func (t taskProgress) Detail() string { func (t taskProgress) Error() error { if t.info.Error != nil { - return Error{t.info.Error} + return Error{t.info.Error, t.info.Description} } return nil @@ -68,7 +68,7 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool { t.info = &ti } - // t.info could be nil if pc can't satify the rules above + // t.info could be nil if pc can't satisfy the rules above if t.info == nil { return false } @@ -99,7 +99,7 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool { } } -// Wait waits for a task to finish with either success or failure. It does so +// WaitEx waits for a task to finish with either success or failure. It does so // by waiting for the "info" property of task managed object to change. The // function returns when it finds the task in the "success" or "error" state. // In the former case, the return value is nil. In the latter case the return @@ -113,8 +113,12 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool { // The detail for the progress update is set to an empty string. If the task // finishes in the error state, the error instance is passed through as well. // Note that this error is the same error that is returned by this function. -// -func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Collector, s progress.Sinker) (*types.TaskInfo, error) { +func WaitEx( + ctx context.Context, + ref types.ManagedObjectReference, + pc *property.Collector, + s progress.Sinker) (*types.TaskInfo, error) { + cb := &taskCallback{} // Include progress sink if specified @@ -123,8 +127,29 @@ func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Co defer close(cb.ch) } - err := property.Wait(ctx, pc, ref, []string{"info"}, cb.fn) - if err != nil { + filter := &property.WaitFilter{ + WaitOptions: property.WaitOptions{ + PropagateMissing: true, + }, + } + filter.Add(ref, ref.Type, []string{"info"}) + + if err := property.WaitForUpdatesEx( + ctx, + pc, + filter, + func(updates []types.ObjectUpdate) bool { + for _, update := range updates { + // Only look at updates for the expected task object. + if update.Obj.Value == ref.Value && update.Obj.Type == ref.Type { + if cb.fn(update.ChangeSet) { + return true + } + } + } + return false + }); err != nil { + return nil, err } diff --git a/vendor/github.com/vmware/govmomi/vapi/internal/internal.go b/vendor/github.com/vmware/govmomi/vapi/internal/internal.go new file mode 100644 index 0000000000..2872f38030 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/internal/internal.go @@ -0,0 +1,93 @@ +/* +Copyright (c) 2018-2023 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 internal + +import ( + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" +) + +// VAPI REST Paths +const ( + SessionPath = "/com/vmware/cis/session" + CategoryPath = "/com/vmware/cis/tagging/category" + TagPath = "/com/vmware/cis/tagging/tag" + AssociationPath = "/com/vmware/cis/tagging/tag-association" + LibraryPath = "/com/vmware/content/library" + LibraryItemFileData = "/com/vmware/cis/data" + LibraryItemPath = "/com/vmware/content/library/item" + LibraryItemFilePath = "/com/vmware/content/library/item/file" + LibraryItemUpdateSession = "/com/vmware/content/library/item/update-session" + LibraryItemUpdateSessionFile = "/com/vmware/content/library/item/updatesession/file" + LibraryItemDownloadSession = "/com/vmware/content/library/item/download-session" + LibraryItemDownloadSessionFile = "/com/vmware/content/library/item/downloadsession/file" + LocalLibraryPath = "/com/vmware/content/local-library" + SubscribedLibraryPath = "/com/vmware/content/subscribed-library" + SecurityPoliciesPath = "/api/content/security-policies" + SubscribedLibraryItem = "/com/vmware/content/library/subscribed-item" + Subscriptions = "/com/vmware/content/library/subscriptions" + TrustedCertificatesPath = "/api/content/trusted-certificates" + VCenterOVFLibraryItem = "/com/vmware/vcenter/ovf/library-item" + VCenterVMTXLibraryItem = "/vcenter/vm-template/library-items" + SessionCookieName = "vmware-api-session-id" + UseHeaderAuthn = "vmware-use-header-authn" + DebugEcho = "/vc-sim/debug/echo" +) + +// AssociatedObject is the same structure as types.ManagedObjectReference, +// just with a different field name (ID instead of Value). +// In the API we use mo.Reference, this type is only used for wire transfer. +type AssociatedObject struct { + Type string `json:"type"` + Value string `json:"id"` +} + +// Reference implements mo.Reference +func (o AssociatedObject) Reference() types.ManagedObjectReference { + return types.ManagedObjectReference{ + Type: o.Type, + Value: o.Value, + } +} + +// Association for tag-association requests. +type Association struct { + ObjectID *AssociatedObject `json:"object_id,omitempty"` +} + +// NewAssociation returns an Association, converting ref to an AssociatedObject. +func NewAssociation(ref mo.Reference) Association { + return Association{ + ObjectID: &AssociatedObject{ + Type: ref.Reference().Type, + Value: ref.Reference().Value, + }, + } +} + +type SubscriptionDestination struct { + ID string `json:"subscription"` +} + +type SubscriptionDestinationSpec struct { + Subscriptions []SubscriptionDestination `json:"subscriptions,omitempty"` +} + +type SubscriptionItemDestinationSpec struct { + Force bool `json:"force_sync_content"` + Subscriptions []SubscriptionDestination `json:"subscriptions,omitempty"` +} diff --git a/vendor/github.com/vmware/govmomi/vapi/rest/client.go b/vendor/github.com/vmware/govmomi/vapi/rest/client.go new file mode 100644 index 0000000000..52552bf00f --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/rest/client.go @@ -0,0 +1,350 @@ +/* +Copyright (c) 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. +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 rest + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "sync" + "time" + + "github.com/vmware/govmomi/vapi/internal" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +// Client extends soap.Client to support JSON encoding, while inheriting security features, debug tracing and session persistence. +type Client struct { + mu sync.Mutex + + *soap.Client + sessionID string +} + +// Session information +type Session struct { + User string `json:"user"` + Created time.Time `json:"created_time"` + LastAccessed time.Time `json:"last_accessed_time"` +} + +// LocalizableMessage represents a localizable error +type LocalizableMessage struct { + Args []string `json:"args,omitempty"` + DefaultMessage string `json:"default_message,omitempty"` + ID string `json:"id,omitempty"` +} + +func (m *LocalizableMessage) Error() string { + return m.DefaultMessage +} + +// NewClient creates a new Client instance. +func NewClient(c *vim25.Client) *Client { + sc := c.Client.NewServiceClient(Path, "") + + return &Client{Client: sc} +} + +// SessionID is set by calling Login() or optionally with the given id param +func (c *Client) SessionID(id ...string) string { + c.mu.Lock() + defer c.mu.Unlock() + if len(id) != 0 { + c.sessionID = id[0] + } + return c.sessionID +} + +type marshaledClient struct { + SoapClient *soap.Client + SessionID string +} + +func (c *Client) MarshalJSON() ([]byte, error) { + m := marshaledClient{ + SoapClient: c.Client, + SessionID: c.sessionID, + } + + return json.Marshal(m) +} + +func (c *Client) UnmarshalJSON(b []byte) error { + var m marshaledClient + + err := json.Unmarshal(b, &m) + if err != nil { + return err + } + + *c = Client{ + Client: m.SoapClient, + sessionID: m.SessionID, + } + + return nil +} + +// isAPI returns true if path starts with "/api" +// This hack allows helpers to support both endpoints: +// "/rest" - value wrapped responses and structured error responses +// "/api" - raw responses and no structured error responses +func isAPI(path string) bool { + return strings.HasPrefix(path, "/api") +} + +// Resource helper for the given path. +func (c *Client) Resource(path string) *Resource { + r := &Resource{u: c.URL()} + if !isAPI(path) { + path = Path + path + } + r.u.Path = path + return r +} + +type Signer interface { + SignRequest(*http.Request) error +} + +type signerContext struct{} + +func (c *Client) WithSigner(ctx context.Context, s Signer) context.Context { + return context.WithValue(ctx, signerContext{}, s) +} + +type headersContext struct{} + +// WithHeader returns a new Context populated with the provided headers map. +// Calls to a VAPI REST client with this context will populate the HTTP headers +// map using the provided headers. +func (c *Client) WithHeader( + ctx context.Context, + headers http.Header) context.Context { + + return context.WithValue(ctx, headersContext{}, headers) +} + +type statusError struct { + res *http.Response +} + +func (e *statusError) Error() string { + return fmt.Sprintf("%s %s: %s", e.res.Request.Method, e.res.Request.URL, e.res.Status) +} + +func IsStatusError(err error, code int) bool { + statusErr, ok := err.(*statusError) + if !ok || statusErr == nil || statusErr.res == nil { + return false + } + return statusErr.res.StatusCode == code +} + +// RawResponse may be used with the Do method as the resBody argument in order +// to capture the raw response data. +type RawResponse struct { + bytes.Buffer +} + +// Do sends the http.Request, decoding resBody if provided. +func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{}) error { + switch req.Method { + case http.MethodPost, http.MethodPatch, http.MethodPut: + req.Header.Set("Content-Type", "application/json") + } + + req.Header.Set("Accept", "application/json") + + if id := c.SessionID(); id != "" { + req.Header.Set(internal.SessionCookieName, id) + } + + if s, ok := ctx.Value(signerContext{}).(Signer); ok { + if err := s.SignRequest(req); err != nil { + return err + } + } + + // OperationID (see soap.Client.soapRoundTrip) + if id, ok := ctx.Value(types.ID{}).(string); ok { + req.Header.Add("X-Request-ID", id) + } + + if headers, ok := ctx.Value(headersContext{}).(http.Header); ok { + for k, v := range headers { + for _, v := range v { + req.Header.Add(k, v) + } + } + } + + return c.Client.Do(ctx, req, func(res *http.Response) error { + switch res.StatusCode { + case http.StatusOK: + case http.StatusCreated: + case http.StatusAccepted: + case http.StatusNoContent: + case http.StatusBadRequest: + // TODO: structured error types + detail, err := io.ReadAll(res.Body) + if err != nil { + return err + } + return fmt.Errorf("%s: %s", res.Status, bytes.TrimSpace(detail)) + default: + return &statusError{res} + } + + if resBody == nil { + return nil + } + + switch b := resBody.(type) { + case *RawResponse: + return res.Write(b) + case io.Writer: + _, err := io.Copy(b, res.Body) + return err + default: + d := json.NewDecoder(res.Body) + if isAPI(req.URL.Path) { + // Responses from the /api endpoint are not wrapped + return d.Decode(resBody) + } + // Responses from the /rest endpoint are wrapped in this structure + val := struct { + Value interface{} `json:"value,omitempty"` + }{ + resBody, + } + return d.Decode(&val) + } + }) +} + +// authHeaders ensures the given map contains a REST auth header +func (c *Client) authHeaders(h map[string]string) map[string]string { + if _, exists := h[internal.SessionCookieName]; exists { + return h + } + if h == nil { + h = make(map[string]string) + } + + h[internal.SessionCookieName] = c.SessionID() + + return h +} + +// Download wraps soap.Client.Download, adding the REST authentication header +func (c *Client) Download(ctx context.Context, u *url.URL, param *soap.Download) (io.ReadCloser, int64, error) { + p := *param + p.Headers = c.authHeaders(p.Headers) + return c.Client.Download(ctx, u, &p) +} + +// DownloadFile wraps soap.Client.DownloadFile, adding the REST authentication header +func (c *Client) DownloadFile(ctx context.Context, file string, u *url.URL, param *soap.Download) error { + p := *param + p.Headers = c.authHeaders(p.Headers) + return c.Client.DownloadFile(ctx, file, u, &p) +} + +// Upload wraps soap.Client.Upload, adding the REST authentication header +func (c *Client) Upload(ctx context.Context, f io.Reader, u *url.URL, param *soap.Upload) error { + p := *param + p.Headers = c.authHeaders(p.Headers) + return c.Client.Upload(ctx, f, u, &p) +} + +// Login creates a new session via Basic Authentication with the given url.Userinfo. +func (c *Client) Login(ctx context.Context, user *url.Userinfo) error { + req := c.Resource(internal.SessionPath).Request(http.MethodPost) + + req.Header.Set(internal.UseHeaderAuthn, "true") + + if user != nil { + if password, ok := user.Password(); ok { + req.SetBasicAuth(user.Username(), password) + } + } + + var id string + err := c.Do(ctx, req, &id) + if err != nil { + return err + } + + c.SessionID(id) + + return nil +} + +func (c *Client) LoginByToken(ctx context.Context) error { + return c.Login(ctx, nil) +} + +// Session returns the user's current session. +// Nil is returned if the session is not authenticated. +func (c *Client) Session(ctx context.Context) (*Session, error) { + var s Session + req := c.Resource(internal.SessionPath).WithAction("get").Request(http.MethodPost) + err := c.Do(ctx, req, &s) + if err != nil { + if e, ok := err.(*statusError); ok { + if e.res.StatusCode == http.StatusUnauthorized { + return nil, nil + } + } + return nil, err + } + return &s, nil +} + +// Logout deletes the current session. +func (c *Client) Logout(ctx context.Context) error { + req := c.Resource(internal.SessionPath).Request(http.MethodDelete) + return c.Do(ctx, req, nil) +} + +// Valid returns whether or not the client is valid and ready for use. +// This should be called after unmarshalling the client. +func (c *Client) Valid() bool { + if c == nil { + return false + } + + if c.Client == nil { + return false + } + + return true +} + +// Path returns rest.Path (see cache.Client) +func (c *Client) Path() string { + return Path +} diff --git a/vendor/github.com/vmware/govmomi/vapi/rest/resource.go b/vendor/github.com/vmware/govmomi/vapi/rest/resource.go new file mode 100644 index 0000000000..f89e07e3b9 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/rest/resource.go @@ -0,0 +1,120 @@ +/* +Copyright (c) 2019 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 rest + +import ( + "bytes" + "encoding/json" + "io" + "net/http" + "net/url" +) + +const ( + Path = "/rest" +) + +// Resource wraps url.URL with helpers +type Resource struct { + u *url.URL +} + +func (r *Resource) String() string { + return r.u.String() +} + +// WithSubpath appends the provided subpath to the URL.Path +func (r *Resource) WithSubpath(subpath string) *Resource { + r.u.Path += "/" + subpath + return r +} + +// WithID appends id to the URL.Path +func (r *Resource) WithID(id string) *Resource { + r.u.Path += "/id:" + id + return r +} + +// WithAction sets adds action to the URL.RawQuery +func (r *Resource) WithAction(action string) *Resource { + return r.WithParam("~action", action) +} + +// WithParam adds one parameter on the URL.RawQuery +func (r *Resource) WithParam(name string, value string) *Resource { + // ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case + params, err := url.ParseQuery(r.u.RawQuery) + if err != nil { + panic(err) + } + params[name] = append(params[name], value) + r.u.RawQuery = params.Encode() + return r +} + +// WithPathEncodedParam appends a parameter on the URL.RawQuery, +// For special cases where URL Path-style encoding is needed +func (r *Resource) WithPathEncodedParam(name string, value string) *Resource { + t := &url.URL{Path: value} + encodedValue := t.String() + t = &url.URL{Path: name} + encodedName := t.String() + // ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case + params, err := url.ParseQuery(r.u.RawQuery) + if err != nil { + panic(err) + } + // Values.Encode() doesn't escape exactly how we want, so we need to build the query string ourselves + if len(params) >= 1 { + r.u.RawQuery = r.u.RawQuery + "&" + encodedName + "=" + encodedValue + } else { + r.u.RawQuery = r.u.RawQuery + encodedName + "=" + encodedValue + } + return r +} + +// Request returns a new http.Request for the given method. +// An optional body can be provided for POST and PATCH methods. +func (r *Resource) Request(method string, body ...interface{}) *http.Request { + rdr := io.MultiReader() // empty body by default + if len(body) != 0 { + rdr = encode(body[0]) + } + req, err := http.NewRequest(method, r.u.String(), rdr) + if err != nil { + panic(err) + } + return req +} + +type errorReader struct { + e error +} + +func (e errorReader) Read([]byte) (int, error) { + return -1, e.e +} + +// encode body as JSON, deferring any errors until io.Reader is used. +func encode(body interface{}) io.Reader { + var b bytes.Buffer + err := json.NewEncoder(&b).Encode(body) + if err != nil { + return errorReader{err} + } + return &b +} diff --git a/vendor/github.com/vmware/govmomi/view/container_view.go b/vendor/github.com/vmware/govmomi/view/container_view.go index 0e3268b85e..356994035f 100644 --- a/vendor/github.com/vmware/govmomi/view/container_view.go +++ b/vendor/github.com/vmware/govmomi/view/container_view.go @@ -36,7 +36,7 @@ func NewContainerView(c *vim25.Client, ref types.ManagedObjectReference) *Contai } // Retrieve populates dst as property.Collector.Retrieve does, for all entities in the view of types specified by kind. -func (v ContainerView) Retrieve(ctx context.Context, kind []string, ps []string, dst interface{}) error { +func (v ContainerView) Retrieve(ctx context.Context, kind []string, ps []string, dst interface{}, pspec ...types.PropertySpec) error { pc := property.DefaultCollector(v.Client()) ospec := types.ObjectSpec{ @@ -50,8 +50,6 @@ func (v ContainerView) Retrieve(ctx context.Context, kind []string, ps []string, }, } - var pspec []types.PropertySpec - if len(kind) == 0 { kind = []string{"ManagedEntity"} } @@ -89,11 +87,11 @@ func (v ContainerView) Retrieve(ctx context.Context, kind []string, ps []string, return nil } - return mo.LoadRetrievePropertiesResponse(res, dst) + return mo.LoadObjectContent(res.Returnval, dst) } // RetrieveWithFilter populates dst as Retrieve does, but only for entities matching the given filter. -func (v ContainerView) RetrieveWithFilter(ctx context.Context, kind []string, ps []string, dst interface{}, filter property.Filter) error { +func (v ContainerView) RetrieveWithFilter(ctx context.Context, kind []string, ps []string, dst interface{}, filter property.Match) error { if len(filter) == 0 { return v.Retrieve(ctx, kind, ps, dst) } @@ -105,7 +103,7 @@ func (v ContainerView) RetrieveWithFilter(ctx context.Context, kind []string, ps return err } - objs := filter.MatchObjectContent(content) + objs := filter.ObjectContent(content) pc := property.DefaultCollector(v.Client()) @@ -113,10 +111,10 @@ func (v ContainerView) RetrieveWithFilter(ctx context.Context, kind []string, ps } // Find returns object references for entities of type kind, matching the given filter. -func (v ContainerView) Find(ctx context.Context, kind []string, filter property.Filter) ([]types.ManagedObjectReference, error) { +func (v ContainerView) Find(ctx context.Context, kind []string, filter property.Match) ([]types.ManagedObjectReference, error) { if len(filter) == 0 { // Ensure we have at least 1 filter to avoid retrieving all properties. - filter = property.Filter{"name": "*"} + filter = property.Match{"name": "*"} } var content []types.ObjectContent @@ -126,5 +124,22 @@ func (v ContainerView) Find(ctx context.Context, kind []string, filter property. return nil, err } - return filter.MatchObjectContent(content), nil + return filter.ObjectContent(content), nil +} + +// FindAny returns object references for entities of type kind, matching any property the given filter. +func (v ContainerView) FindAny(ctx context.Context, kind []string, filter property.Match) ([]types.ManagedObjectReference, error) { + if len(filter) == 0 { + // Ensure we have at least 1 filter to avoid retrieving all properties. + filter = property.Match{"name": "*"} + } + + var content []types.ObjectContent + + err := v.Retrieve(ctx, kind, filter.Keys(), &content) + if err != nil { + return nil, err + } + + return filter.AnyObjectContent(content), nil } diff --git a/vendor/github.com/vmware/govmomi/view/list_view.go b/vendor/github.com/vmware/govmomi/view/list_view.go index e8cfb50434..4958941cc6 100644 --- a/vendor/github.com/vmware/govmomi/view/list_view.go +++ b/vendor/github.com/vmware/govmomi/view/list_view.go @@ -34,29 +34,41 @@ func NewListView(c *vim25.Client, ref types.ManagedObjectReference) *ListView { } } -func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ModifyListView{ This: v.Reference(), Add: refs, } - _, err := methods.ModifyListView(ctx, v.Client(), &req) - return err + res, err := methods.ModifyListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } -func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ModifyListView{ This: v.Reference(), Remove: refs, } - _, err := methods.ModifyListView(ctx, v.Client(), &req) - return err + res, err := methods.ModifyListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } -func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ResetListView{ This: v.Reference(), Obj: refs, } - _, err := methods.ResetListView(ctx, v.Client(), &req) - return err + res, err := methods.ResetListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } diff --git a/vendor/github.com/vmware/govmomi/view/task_view.go b/vendor/github.com/vmware/govmomi/view/task_view.go index 68f62f8d10..4e1beef38c 100644 --- a/vendor/github.com/vmware/govmomi/view/task_view.go +++ b/vendor/github.com/vmware/govmomi/view/task_view.go @@ -73,7 +73,7 @@ func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error { tasks = change.Val.(types.ArrayOfManagedObjectReference).ManagedObjectReference if len(tasks) != 0 { reset = func() { - _ = v.Reset(ctx, tasks) + _, _ = v.Reset(ctx, tasks) // Remember any tasks we've reported as complete already, // to avoid reporting multiple times when Reset is triggered. @@ -113,7 +113,7 @@ func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error { if reset != nil { reset() } else if len(prune) != 0 { - _ = v.Remove(ctx, prune) + _, _ = v.Remove(ctx, prune) } if len(tasks) != 0 && len(infos) == 0 { diff --git a/vendor/github.com/vmware/govmomi/vim25/client.go b/vendor/github.com/vmware/govmomi/vim25/client.go index 1d26fb8b6a..7349183abe 100644 --- a/vendor/github.com/vmware/govmomi/vim25/client.go +++ b/vendor/github.com/vmware/govmomi/vim25/client.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 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 +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, @@ -28,7 +28,7 @@ import ( const ( Namespace = "vim25" - Version = "6.7" + Version = "8.0.2.0" Path = "/sdk" ) @@ -54,7 +54,7 @@ type Client struct { RoundTripper soap.RoundTripper } -// NewClient creates and returns a new client wirh the ServiceContent field +// NewClient creates and returns a new client with the ServiceContent field // filled in. func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) { c := Client{ @@ -67,7 +67,7 @@ func NewClient(ctx context.Context, rt soap.RoundTripper) (*Client, error) { if c.Namespace == "" { c.Namespace = "urn:" + Namespace - } else if strings.Index(c.Namespace, ":") < 0 { + } else if !strings.Contains(c.Namespace, ":") { c.Namespace = "urn:" + c.Namespace // ensure valid URI format } if c.Version == "" { @@ -140,6 +140,11 @@ func (c *Client) Valid() bool { return true } +// Path returns vim25.Path (see cache.Client) +func (c *Client) Path() string { + return Path +} + // IsVC returns true if we are connected to a vCenter func (c *Client) IsVC() bool { return c.ServiceContent.About.ApiType == "VirtualCenter" diff --git a/vendor/github.com/vmware/govmomi/vim25/debug/debug.go b/vendor/github.com/vmware/govmomi/vim25/debug/debug.go index 22d5471784..048062825d 100644 --- a/vendor/github.com/vmware/govmomi/vim25/debug/debug.go +++ b/vendor/github.com/vmware/govmomi/vim25/debug/debug.go @@ -18,8 +18,7 @@ package debug import ( "io" - "os" - "path" + "regexp" ) // Provider specified the interface types must implement to be used as a @@ -30,7 +29,22 @@ type Provider interface { Flush() } +// ReadCloser is a struct that satisfies the io.ReadCloser interface +type ReadCloser struct { + io.Reader + io.Closer +} + +// NewTeeReader wraps io.TeeReader and patches through the Close() function. +func NewTeeReader(rc io.ReadCloser, w io.Writer) io.ReadCloser { + return ReadCloser{ + Reader: io.TeeReader(rc, w), + Closer: rc, + } +} + var currentProvider Provider = nil +var scrubPassword = regexp.MustCompile(`(.*)`) func SetProvider(p Provider) { if currentProvider != nil { @@ -54,28 +68,6 @@ func Flush() { currentProvider.Flush() } -// FileProvider implements a debugging provider that creates a real file for -// every call to NewFile. It maintains a list of all files that it creates, -// such that it can close them when its Flush function is called. -type FileProvider struct { - Path string - - files []*os.File -} - -func (fp *FileProvider) NewFile(p string) io.WriteCloser { - f, err := os.Create(path.Join(fp.Path, p)) - if err != nil { - panic(err) - } - - fp.files = append(fp.files, f) - - return f -} - -func (fp *FileProvider) Flush() { - for _, f := range fp.files { - f.Close() - } +func Scrub(in []byte) []byte { + return scrubPassword.ReplaceAll(in, []byte(`********`)) } diff --git a/vendor/github.com/vmware/govmomi/vim25/debug/file.go b/vendor/github.com/vmware/govmomi/vim25/debug/file.go new file mode 100644 index 0000000000..4290a29167 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/debug/file.go @@ -0,0 +1,75 @@ +/* +Copyright (c) 2014 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 debug + +import ( + "io" + "os" + "path" + "sync" +) + +// FileProvider implements a debugging provider that creates a real file for +// every call to NewFile. It maintains a list of all files that it creates, +// such that it can close them when its Flush function is called. +type FileProvider struct { + Path string + + mu sync.Mutex + files []*os.File +} + +func (fp *FileProvider) NewFile(p string) io.WriteCloser { + f, err := os.Create(path.Join(fp.Path, p)) + if err != nil { + panic(err) + } + + fp.mu.Lock() + defer fp.mu.Unlock() + fp.files = append(fp.files, f) + + return NewFileWriterCloser(f, p) +} + +func (fp *FileProvider) Flush() { + fp.mu.Lock() + defer fp.mu.Unlock() + for _, f := range fp.files { + f.Close() + } +} + +type FileWriterCloser struct { + f *os.File + p string +} + +func NewFileWriterCloser(f *os.File, p string) *FileWriterCloser { + return &FileWriterCloser{ + f, + p, + } +} + +func (fwc *FileWriterCloser) Write(p []byte) (n int, err error) { + return fwc.f.Write(Scrub(p)) +} + +func (fwc *FileWriterCloser) Close() error { + return fwc.f.Close() +} diff --git a/vendor/github.com/vmware/govmomi/vim25/debug/log.go b/vendor/github.com/vmware/govmomi/vim25/debug/log.go new file mode 100644 index 0000000000..183c606a3c --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/debug/log.go @@ -0,0 +1,49 @@ +/* +Copyright (c) 2014 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 debug + +import ( + "fmt" + "io" + "os" +) + +type LogWriterCloser struct { +} + +func NewLogWriterCloser() *LogWriterCloser { + return &LogWriterCloser{} +} + +func (lwc *LogWriterCloser) Write(p []byte) (n int, err error) { + fmt.Fprint(os.Stderr, string(Scrub(p))) + return len(p), nil +} + +func (lwc *LogWriterCloser) Close() error { + return nil +} + +type LogProvider struct { +} + +func (s *LogProvider) NewFile(p string) io.WriteCloser { + return NewLogWriterCloser() +} + +func (s *LogProvider) Flush() { +} diff --git a/vendor/github.com/vmware/govmomi/vim25/json/LICENSE b/vendor/github.com/vmware/govmomi/vim25/json/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/vmware/govmomi/vim25/json/README.md b/vendor/github.com/vmware/govmomi/vim25/json/README.md new file mode 100644 index 0000000000..6cbe80349a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/README.md @@ -0,0 +1,9 @@ +# JSON with Discriminators + +The source code in this directory was copied from Go 1.17.13's `encoding/json` package in order to add support for JSON discriminators. Please use the following command to review the diff: + +```shell +C1="$(git log --pretty=format:'%h' --no-patch --grep='Vendor Go 1.17.13 encoding/json')" && \ +C2="$(git log --pretty=format:'%h' --no-patch --grep='JSON Encoding w Discriminator Support')" && \ +git diff "${C1}".."${C2}" +``` diff --git a/vendor/github.com/vmware/govmomi/vim25/json/decode.go b/vendor/github.com/vmware/govmomi/vim25/json/decode.go new file mode 100644 index 0000000000..6a92a2410b --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/decode.go @@ -0,0 +1,1319 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "encoding" + "encoding/base64" + "fmt" + "reflect" + "strconv" + "strings" + "unicode" + "unicode/utf16" + "unicode/utf8" +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. If v is nil or not a pointer, +// Unmarshal returns an InvalidUnmarshalError. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a value implementing the Unmarshaler interface, +// Unmarshal calls that value's UnmarshalJSON method, including +// when the input is a JSON null. +// Otherwise, if the value implements encoding.TextUnmarshaler +// and the input is a JSON quoted string, Unmarshal calls that value's +// UnmarshalText method with the unquoted form of the string. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. By +// default, object keys which don't have a corresponding struct field are +// ignored (see Decoder.DisallowUnknownFields for an alternative). +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a map, Unmarshal first establishes a map to +// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal +// reuses the existing map, keeping existing entries. Unmarshal then stores +// key-value pairs from the JSON object into the map. The map's key type must +// either be any string type, an integer, implement json.Unmarshaler, or +// implement encoding.TextUnmarshaler. +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshaling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. In any +// case, it's not guaranteed that all the remaining fields following +// the problematic one will be unmarshaled into the target object. +// +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// ``not present,'' unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +// +func Unmarshal(data []byte, v interface{}) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + var d decodeState + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + d.init(data) + return d.unmarshal(v) +} + +// Unmarshaler is the interface implemented by types +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +// +// By convention, to approximate the behavior of Unmarshal itself, +// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes + Struct string // name of the struct type containing the field + Field string // the full path from root node to the field +} + +func (e *UnmarshalTypeError) Error() string { + if e.Struct != "" || e.Field != "" { + return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() + } + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Ptr { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v interface{}) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + d.scanWhile(scanSkipSpace) + // We decode rv not rv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + err := d.value(rv) + if err != nil { + return d.addErrorContext(err) + } + return d.savedError +} + +// A Number represents a JSON number literal. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// An errorContext provides context for type errors during decoding. +type errorContext struct { + Struct reflect.Type + FieldStack []string +} + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // next read offset in data + opcode int // last read result + scan scanner + errorContext *errorContext + savedError error + useNumber bool + disallowUnknownFields bool + + discriminatorTypeFieldName string + discriminatorValueFieldName string + discriminatorToTypeFn DiscriminatorToTypeFunc +} + +// readIndex returns the position of the last byte read. +func (d *decodeState) readIndex() int { + return d.off - 1 +} + +// phasePanicMsg is used as a panic message when we end up with something that +// shouldn't happen. It can indicate a bug in the JSON decoder, or that +// something is editing the data slice while the decoder executes. +const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?" + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + if d.errorContext != nil { + d.errorContext.Struct = nil + // Reuse the allocated space for the FieldStack slice. + d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + } + return d +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = d.addErrorContext(err) + } +} + +// addErrorContext returns a new error enhanced with information from d.errorContext +func (d *decodeState) addErrorContext(err error) error { + if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { + switch err := err.(type) { + case *UnmarshalTypeError: + err.Struct = d.errorContext.Struct.Name() + err.Field = strings.Join(d.errorContext.FieldStack, ".") + } + } + return err +} + +// skip scans to the end of what was started. +func (d *decodeState) skip() { + s, data, i := &d.scan, d.data, d.off + depth := len(s.parseState) + for { + op := s.step(s, data[i]) + i++ + if len(s.parseState) < depth { + d.off = i + d.opcode = op + return + } + } +} + +// scanNext processes the byte at d.data[d.off]. +func (d *decodeState) scanNext() { + if d.off < len(d.data) { + d.opcode = d.scan.step(&d.scan, d.data[d.off]) + d.off++ + } else { + d.opcode = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +func (d *decodeState) scanWhile(op int) { + s, data, i := &d.scan, d.data, d.off + for i < len(data) { + newOp := s.step(s, data[i]) + i++ + if newOp != op { + d.opcode = newOp + d.off = i + return + } + } + + d.off = len(data) + 1 // mark processed EOF with len+1 + d.opcode = d.scan.eof() +} + +// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the +// common case where we're decoding a literal. The decoder scans the input +// twice, once for syntax errors and to check the length of the value, and the +// second to perform the decoding. +// +// Only in the second step do we use decodeState to tokenize literals, so we +// know there aren't any syntax errors. We can take advantage of that knowledge, +// and scan a literal's bytes much more quickly. +func (d *decodeState) rescanLiteral() { + data, i := d.data, d.off +Switch: + switch data[i-1] { + case '"': // string + for ; i < len(data); i++ { + switch data[i] { + case '\\': + i++ // escaped char + case '"': + i++ // tokenize the closing quote too + break Switch + } + } + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number + for ; i < len(data); i++ { + switch data[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', 'e', 'E', '+', '-': + default: + break Switch + } + } + case 't': // true + i += len("rue") + case 'f': // false + i += len("alse") + case 'n': // null + i += len("ull") + } + if i < len(data) { + d.opcode = stateEndValue(&d.scan, data[i]) + } else { + d.opcode = scanEnd + } + d.off = i + 1 +} + +// value consumes a JSON value from d.data[d.off-1:], decoding into v, and +// reads the following byte ahead. If v is invalid, the value is discarded. +// The first byte of the value has been read already. +func (d *decodeState) value(v reflect.Value) error { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray: + if v.IsValid() { + if err := d.array(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginObject: + if v.IsValid() { + if err := d.object(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginLiteral: + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + if v.IsValid() { + if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { + return err + } + } + } + return nil +} + +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() interface{} { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray, scanBeginObject: + d.skip() + d.scanNext() + + case scanBeginLiteral: + v := d.literalInterface() + switch v.(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// If it encounters an Unmarshaler, indirect stops and returns that. +// If decodingNull is true, indirect stops at the first settable pointer so it +// can be set to nil. +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // Issue #24153 indicates that it is generally not a guaranteed property + // that you may round-trip a reflect.Value by calling Value.Addr().Elem() + // and expect the value to still be settable for values derived from + // unexported embedded struct fields. + // + // The logic below effectively does this when it first addresses the value + // (to satisfy possible pointer methods) and continues to dereference + // subsequent pointers as necessary. + // + // After the first round-trip, we set v back to the original value to + // preserve the original RW flags contained in reflect.Value. + v0 := v + haveAddr := false + + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + haveAddr = true + v = v.Addr() + } + for { + // Load value from interface, but only if the result will be + // usefully addressable. + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + haveAddr = false + v = e + continue + } + } + + if v.Kind() != reflect.Ptr { + break + } + + if decodingNull && v.CanSet() { + break + } + + // Prevent infinite loop if v is an interface pointing to its own address: + // var v interface{} + // v = &v + if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v { + v = v.Elem() + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 && v.CanInterface() { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, nil, reflect.Value{} + } + if !decodingNull { + if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return nil, u, reflect.Value{} + } + } + } + + if haveAddr { + v = v0 // restore original value after round-trip Value.Addr().Elem() + haveAddr = false + } else { + v = v.Elem() + } + } + return nil, nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into v. +// The first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + + // Check type of target. + switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + ai := d.arrayInterface() + v.Set(reflect.ValueOf(ai)) + return nil + } + // Otherwise it's invalid. + fallthrough + default: + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + case reflect.Array, reflect.Slice: + break + } + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + // Get element of array, growing if necessary. + if v.Kind() == reflect.Slice { + // Grow slice if necessary + if i >= v.Cap() { + newcap := v.Cap() + v.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) + reflect.Copy(newv, v) + v.Set(newv) + } + if i >= v.Len() { + v.SetLen(i + 1) + } + } + + if i < v.Len() { + // Decode into element. + if err := d.value(v.Index(i)); err != nil { + return err + } + } else { + // Ran out of fixed array: skip. + if err := d.value(reflect.Value{}); err != nil { + return err + } + } + i++ + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + + if i < v.Len() { + if v.Kind() == reflect.Array { + // Array. Zero the rest. + z := reflect.Zero(v.Type().Elem()) + for ; i < v.Len(); i++ { + v.Index(i).Set(z) + } + } else { + v.SetLen(i) + } + } + if i == 0 && v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } + return nil +} + +var nullLiteral = []byte("null") +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + +// object consumes an object from d.data[d.off-1:], decoding into v. +// The first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + t := v.Type() + + // Decoding into nil interface? Switch to non-reflect code. + if v.Kind() == reflect.Interface && v.NumMethod() == 0 && !d.isDiscriminatorSet() { + oi := d.objectInterface() + v.Set(reflect.ValueOf(oi)) + return nil + } + + var fields structFields + + // Check type of target: + // struct or + // map[T1]T2 where T1 is string, an integer type, + // or an encoding.TextUnmarshaler + switch v.Kind() { + case reflect.Map: + // Map key must either have string kind, have an integer kind, + // or be an encoding.TextUnmarshaler. + switch t.Key().Kind() { + case reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + default: + if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) { + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + fields = cachedTypeFields(t) + // ok + default: + if d.isDiscriminatorSet() { + return d.discriminatorInterfaceDecode(t, v) + } + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + + var mapElem reflect.Value + var origErrorContext errorContext + if d.errorContext != nil { + origErrorContext = *d.errorContext + } + + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquoteBytes(item) + if !ok { + panic(phasePanicMsg) + } + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if v.Kind() == reflect.Map { + elemType := t.Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.Set(reflect.Zero(elemType)) + } + subv = mapElem + } else { + var f *field + if i, ok := fields.nameIndex[string(key)]; ok { + // Found an exact name match. + f = &fields.list[i] + } else { + // Fall back to the expensive case-insensitive + // linear search. + for i := range fields.list { + ff := &fields.list[i] + if ff.equalFold(ff.nameBytes, key) { + f = ff + break + } + } + } + if f != nil { + subv = v + destring = f.quoted + for _, i := range f.index { + if subv.Kind() == reflect.Ptr { + if subv.IsNil() { + // If a struct embeds a pointer to an unexported type, + // it is not possible to set a newly allocated value + // since the field is unexported. + // + // See https://golang.org/issue/21357 + if !subv.CanSet() { + d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) + // Invalidate subv to ensure d.value(subv) skips over + // the JSON value without assigning it to subv. + subv = reflect.Value{} + destring = false + break + } + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + subv = subv.Field(i) + } + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) + d.errorContext.Struct = t + } else if d.disallowUnknownFields { + d.saveError(fmt.Errorf("json: unknown field %q", key)) + } + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + if destring { + switch qv := d.valueQuoted().(type) { + case nil: + if err := d.literalStore(nullLiteral, subv, false); err != nil { + return err + } + case string: + if err := d.literalStore([]byte(qv), subv, true); err != nil { + return err + } + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) + } + } else { + if err := d.value(subv); err != nil { + return err + } + } + + // Write value back to map; + // if using struct, subv points into struct already. + if v.Kind() == reflect.Map { + kt := t.Key() + var kv reflect.Value + switch { + case reflect.PtrTo(kt).Implements(textUnmarshalerType): + kv = reflect.New(kt) + if err := d.literalStore(item, kv, true); err != nil { + return err + } + kv = kv.Elem() + case kt.Kind() == reflect.String: + kv = reflect.ValueOf(key).Convert(kt) + default: + switch kt.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + s := string(key) + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + s := string(key) + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + default: + panic("json: Unexpected key type") // should never occur + } + } + if kv.IsValid() { + if !d.isDiscriminatorSet() || kv.String() != d.discriminatorTypeFieldName { + v.SetMapIndex(kv, subv) + } + } + } + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.errorContext != nil { + // Reset errorContext to its original state. + // Keep the same underlying array for FieldStack, to reuse the + // space and avoid unnecessary allocs. + d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] + d.errorContext.Struct = origErrorContext.Struct + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return nil +} + +// convertNumber converts the number literal s to a float64 or a Number +// depending on the setting of d.useNumber. +func (d *decodeState) convertNumber(s string) (interface{}, error) { + if d.useNumber { + return Number(s), nil + } + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)} + } + return f, nil +} + +var numberType = reflect.TypeOf(Number("")) + +// literalStore decodes a literal stored in item into v. +// +// fromQuoted indicates whether this literal came from unwrapping a +// string from the ",string" struct tag option. this is used only to +// produce more helpful error messages. +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { + // Check for unmarshaler. + if len(item) == 0 { + //Empty string given + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + isNull := item[0] == 'n' // null + u, ut, pv := indirect(v, isNull) + if u != nil { + return u.UnmarshalJSON(item) + } + if ut != nil { + if item[0] != '"' { + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + val := "number" + switch item[0] { + case 'n': + val = "null" + case 't', 'f': + val = "bool" + } + d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) + return nil + } + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + return ut.UnmarshalText(s) + } + + v = pv + + switch c := item[0]; c { + case 'n': // null + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "null" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + v.Set(reflect.Zero(v.Type())) + // otherwise, ignore null for primitives/string + } + case 't', 'f': // true, false + value := item[0] == 't' + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "true" && string(item) != "false" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + default: + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Slice: + if v.Type().Elem().Kind() != reflect.Uint8 { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.SetBytes(b[:n]) + case reflect.String: + if v.Type() == numberType && !isValidNumber(string(s)) { + return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) + } + v.SetString(string(s)) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + s := string(item) + switch v.Kind() { + default: + if v.Kind() == reflect.String && v.Type() == numberType { + // s must be a valid number, because it's + // already been tokenized. + v.SetString(s) + break + } + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Interface: + n, err := d.convertNumber(s) + if err != nil { + d.saveError(err) + break + } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.ParseFloat(s, v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetFloat(n) + } + } + return nil +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns interface{} +func (d *decodeState) valueInterface() (val interface{}) { + switch d.opcode { + default: + panic(phasePanicMsg) + case scanBeginArray: + val = d.arrayInterface() + d.scanNext() + case scanBeginObject: + val = d.objectInterface() + d.scanNext() + case scanBeginLiteral: + val = d.literalInterface() + } + return +} + +// arrayInterface is like array but returns []interface{}. +func (d *decodeState) arrayInterface() []interface{} { + var v = make([]interface{}, 0) + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + return v +} + +// objectInterface is like object but returns map[string]interface{}. +func (d *decodeState) objectInterface() map[string]interface{} { + m := make(map[string]interface{}) + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read string key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return m +} + +// literalInterface consumes and returns a literal from d.data[d.off-1:] and +// it reads the following byte ahead. The first byte of the literal has been +// read already (that's how the caller knows it's a literal). +func (d *decodeState) literalInterface() interface{} { + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + item := d.data[start:d.readIndex()] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + panic(phasePanicMsg) + } + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + } + return n + } +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + var r rune + for _, c := range s[2:6] { + switch { + case '0' <= c && c <= '9': + c = c - '0' + case 'a' <= c && c <= 'f': + c = c - 'a' + 10 + case 'A' <= c && c <= 'F': + c = c - 'A' + 10 + default: + return -1 + } + r = r*16 + rune(c) + } + return r +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go b/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go new file mode 100644 index 0000000000..ce315dd527 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go @@ -0,0 +1,568 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package json + +import ( + "fmt" + "reflect" + "regexp" + "strconv" + "sync" +) + +// DiscriminatorToTypeFunc is used to get a reflect.Type from its +// discriminator. +type DiscriminatorToTypeFunc func(discriminator string) (reflect.Type, bool) + +// TypeToDiscriminatorFunc is used to get a discriminator string from a +// reflect.Type. Empty return value suppresses discriminator rendering. +type TypeToDiscriminatorFunc func(reflect.Type) (discriminator string) + +// DefaultDiscriminatorFunc is shorthand for the ShortName func and is used when +// no other discriminator func is set explicitly +var DefaultDiscriminatorFunc = ShortName + +// ShortName returns the type name in golang without the package name +func ShortName(t reflect.Type) (discriminator string) { + tn := t.Name() + if tn == "" { + return t.String() + } + return tn +} + +// FullName return the name of the type prefixed with the package name as +// appropriate +func FullName(t reflect.Type) (discriminator string) { + tn := t.Name() + if tn == "" { + return t.String() + } + if pp := t.PkgPath(); pp != "" { + return fmt.Sprintf("%s.%s", pp, tn) + } + return tn +} + +// DiscriminatorEncodeMode is a mask that describes the different encode +// options. +type DiscriminatorEncodeMode uint8 + +const ( + // DiscriminatorEncodeTypeNameRootValue causes the type name to be encoded + // for the root value. + DiscriminatorEncodeTypeNameRootValue DiscriminatorEncodeMode = 1 << iota + + // DiscriminatorEncodeTypeNameAllObjects causes the type name to be encoded + // for all struct and map values. Please note this specifically does not + // apply to the root value. + DiscriminatorEncodeTypeNameAllObjects + + // DiscriminatorEncodeTypeNameIfRequired is the default behavior when + // the discriminator is set, and the type name is only encoded if required. + DiscriminatorEncodeTypeNameIfRequired DiscriminatorEncodeMode = 0 +) + +func (m DiscriminatorEncodeMode) root() bool { + return m&DiscriminatorEncodeTypeNameRootValue > 0 +} + +func (m DiscriminatorEncodeMode) all() bool { + return m&DiscriminatorEncodeTypeNameAllObjects > 0 +} + +func (d *decodeState) isDiscriminatorSet() bool { + return d.discriminatorTypeFieldName != "" && + d.discriminatorValueFieldName != "" +} + +// discriminatorOpType describes the current operation related to +// discriminators when reading a JSON object's fields. +type discriminatorOpType uint8 + +const ( + // discriminatorOpTypeNameField indicates the discriminator type name + // field was discovered. + discriminatorOpTypeNameField = iota + 1 + + // discriminatorOpValueField indicates the discriminator value field + // was discovered. + discriminatorOpValueField +) + +func (d *decodeState) discriminatorGetValue() (reflect.Value, error) { + // Record the current offset so we know where the data starts. + offset := d.readIndex() + + // Create a temporary decodeState used to inspect the current object + // and determine its discriminator type and decode its value. + dd := &decodeState{ + disallowUnknownFields: d.disallowUnknownFields, + useNumber: d.useNumber, + discriminatorToTypeFn: d.discriminatorToTypeFn, + discriminatorTypeFieldName: d.discriminatorTypeFieldName, + discriminatorValueFieldName: d.discriminatorValueFieldName, + } + dd.init(append([]byte{}, d.data[offset:]...)) + defer freeScanner(&dd.scan) + dd.scan.reset() + + var ( + t reflect.Type // the instance of the type + valueOff = -1 // the offset of a possible discriminator value + ) + + dd.scanWhile(scanSkipSpace) + if dd.opcode != scanBeginObject { + panic(phasePanicMsg) + } + + for { + dd.scanWhile(scanSkipSpace) + if dd.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if dd.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := dd.readIndex() + dd.rescanLiteral() + item := dd.data[start:dd.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Check to see if the key is related to the discriminator. + var discriminatorOp discriminatorOpType + switch key { + case d.discriminatorTypeFieldName: + discriminatorOp = discriminatorOpTypeNameField + case d.discriminatorValueFieldName: + discriminatorOp = discriminatorOpValueField + } + + // Read : before value. + if dd.opcode == scanSkipSpace { + dd.scanWhile(scanSkipSpace) + } + + if dd.opcode != scanObjectKey { + panic(phasePanicMsg) + } + dd.scanWhile(scanSkipSpace) + + // Read value. + valOff := dd.readIndex() + val := dd.valueInterface() + + switch discriminatorOp { + case discriminatorOpTypeNameField: + tn, ok := val.(string) + if !ok { + return reflect.Value{}, fmt.Errorf( + "json: discriminator type at offset %d is not string", + offset+valOff) + } + if tn == "" { + return reflect.Value{}, fmt.Errorf( + "json: discriminator type at offset %d is empty", + offset+valOff) + } + + // Parse the type name into a type instance. + ti, err := discriminatorParseTypeName(tn, d.discriminatorToTypeFn) + if err != nil { + return reflect.Value{}, err + } + + // Assign the type instance to the outer variable, t. + t = ti + + // Primitive types and types with Unmarshaler are wrapped in a + // structure with type and value fields. Structures and Maps not + // implementing Unmarshaler use discriminator embedded within their + // content. + if useNestedDiscriminator(t) { + // If the type is a map or a struct not implementing Unmarshaler + // then it is not necessary to continue walking over the current + // JSON object since it will be completely re-scanned to decode + // its value into the discovered type. + dd.opcode = scanEndObject + } else { + // Otherwise if the value offset has been discovered then it is + // safe to stop walking over the current JSON object as well. + if valueOff > -1 { + dd.opcode = scanEndObject + } + } + case discriminatorOpValueField: + valueOff = valOff + + // If the type has been discovered then it is safe to stop walking + // over the current JSON object. + if t != nil { + dd.opcode = scanEndObject + } + } + + // Next token must be , or }. + if dd.opcode == scanSkipSpace { + dd.scanWhile(scanSkipSpace) + } + if dd.opcode == scanEndObject { + break + } + if dd.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + + // If there is not a type discriminator then return early. + if t == nil { + return reflect.Value{}, fmt.Errorf("json: missing discriminator") + } + + // Instantiate a new instance of the discriminated type. + var v reflect.Value + switch t.Kind() { + case reflect.Slice: + // MakeSlice returns a value that is not addressable. + // Instead, use MakeSlice to get the type, then use + // reflect.New to create an addressable value. + v = reflect.New(reflect.MakeSlice(t, 0, 0).Type()).Elem() + case reflect.Map: + // MakeMap returns a value that is not addressable. + // Instead, use MakeMap to get the type, then use + // reflect.New to create an addressable value. + v = reflect.New(reflect.MakeMap(t).Type()).Elem() + case reflect.Complex64, reflect.Complex128: + return reflect.Value{}, fmt.Errorf("json: unsupported discriminator type: %s", t.Kind()) + default: + v = reflect.New(t) + } + + // Reset the decode state to prepare for decoding the data. + dd.scan.reset() + + if useNestedDiscriminator(t) { + // Set the offset to zero since the entire object will be decoded + // into v. + dd.off = 0 + } else { + // Set the offset to what it was before the discriminator value was + // read so only the value field is decoded into v. + dd.off = valueOff + } + // This will initialize the correct scan step and op code. + dd.scanWhile(scanSkipSpace) + + // Decode the data into the value. + if err := dd.value(v); err != nil { + return reflect.Value{}, err + } + + // Check the saved error as well since the decoder.value function does not + // always return an error. If the reflected value is still zero, then it is + // likely the decoder was unable to decode the value. + if err := dd.savedError; err != nil { + switch v.Kind() { + case reflect.Ptr, reflect.Interface: + v = v.Elem() + } + if v.IsZero() { + return reflect.Value{}, err + } + } + + return v, nil +} + +func (d *decodeState) discriminatorInterfaceDecode(t reflect.Type, v reflect.Value) error { + + defer func() { + // Advance the decode state, throwing away the value. + _ = d.objectInterface() + }() + + dv, err := d.discriminatorGetValue() + if err != nil { + return err + } + + switch dv.Kind() { + case reflect.Map, reflect.Slice: + if dv.Type().AssignableTo(t) { + v.Set(dv) + return nil + } + if pdv := dv.Addr(); pdv.Type().AssignableTo(t) { + v.Set(pdv) + return nil + } + case reflect.Ptr: + if dve := dv.Elem(); dve.Type().AssignableTo(t) { + v.Set(dve) + return nil + } + if dv.Type().AssignableTo(t) { + v.Set(dv) + return nil + } + } + + return fmt.Errorf("json: unsupported discriminator kind: %s", dv.Kind()) +} + +func (o encOpts) isDiscriminatorSet() bool { + return o.discriminatorTypeFieldName != "" && + o.discriminatorValueFieldName != "" +} + +func discriminatorInterfaceEncode(e *encodeState, v reflect.Value, opts encOpts) { + v = v.Elem() + + if v.Type().Implements(marshalerType) { + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + marshalerEncoder(e, v, opts) + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteString(`","`) + e.WriteString(opts.discriminatorValueFieldName) + e.WriteString(`":`) + marshalerEncoder(e, v, opts) + e.WriteByte('}') + return + } + + switch v.Kind() { + case reflect.Chan, reflect.Func, reflect.Invalid: + e.error(&UnsupportedValueError{v, fmt.Sprintf("invalid kind: %s", v.Kind())}) + case reflect.Map: + e.discriminatorEncodeTypeName = true + newMapEncoder(v.Type())(e, v, opts) + case reflect.Struct: + e.discriminatorEncodeTypeName = true + newStructEncoder(v.Type())(e, v, opts) + case reflect.Ptr: + discriminatorInterfaceEncode(e, v, opts) + default: + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + e.reflectValue(v, opts) + return + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteString(`","`) + e.WriteString(opts.discriminatorValueFieldName) + e.WriteString(`":`) + e.reflectValue(v, opts) + e.WriteByte('}') + } +} + +func discriminatorMapEncode(e *encodeState, v reflect.Value, opts encOpts) { + if !e.discriminatorEncodeTypeName && !opts.discriminatorEncodeMode.all() { + return + } + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + return + } + e.WriteByte('"') + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteByte('"') + if v.Len() > 0 { + e.WriteByte(',') + } + e.discriminatorEncodeTypeName = false +} + +func discriminatorStructEncode(e *encodeState, v reflect.Value, opts encOpts) byte { + if !e.discriminatorEncodeTypeName && !opts.discriminatorEncodeMode.all() { + return '{' + } + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + return '{' + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteByte('"') + e.discriminatorEncodeTypeName = false + return ',' +} + +var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() + +// Discriminator is nested in map and struct unless they implement Unmarshaler. +func useNestedDiscriminator(t reflect.Type) bool { + if t.Implements(unmarshalerType) || reflect.PtrTo(t).Implements(unmarshalerType) { + return false + } + kind := t.Kind() + if kind == reflect.Struct || kind == reflect.Map { + return true + } + return false +} + +var discriminatorTypeRegistry = map[string]reflect.Type{ + "uint": reflect.TypeOf(uint(0)), + "uint8": reflect.TypeOf(uint8(0)), + "uint16": reflect.TypeOf(uint16(0)), + "uint32": reflect.TypeOf(uint32(0)), + "uint64": reflect.TypeOf(uint64(0)), + "uintptr": reflect.TypeOf(uintptr(0)), + "int": reflect.TypeOf(int(0)), + "int8": reflect.TypeOf(int8(0)), + "int16": reflect.TypeOf(int16(0)), + "int32": reflect.TypeOf(int32(0)), + "int64": reflect.TypeOf(int64(0)), + "float32": reflect.TypeOf(float32(0)), + "float64": reflect.TypeOf(float64(0)), + "bool": reflect.TypeOf(true), + "string": reflect.TypeOf(""), + "any": reflect.TypeOf((*interface{})(nil)).Elem(), + "interface{}": reflect.TypeOf((*interface{})(nil)).Elem(), + "interface {}": reflect.TypeOf((*interface{})(nil)).Elem(), + + // Not supported, but here to prevent the decoder from panicing + // if encountered. + "complex64": reflect.TypeOf(complex64(0)), + "complex128": reflect.TypeOf(complex128(0)), +} + +// discriminatorPointerTypeCache caches the pointer type for another type. +// For example, a key that was the int type would have a value that is the +// *int type. +var discriminatorPointerTypeCache sync.Map // map[reflect.Type]reflect.Type + +// cachedPointerType returns the pointer type for another and avoids repeated +// work by using a cache. +func cachedPointerType(t reflect.Type) reflect.Type { + if value, ok := discriminatorPointerTypeCache.Load(t); ok { + return value.(reflect.Type) + } + pt := reflect.New(t).Type() + value, _ := discriminatorPointerTypeCache.LoadOrStore(t, pt) + return value.(reflect.Type) +} + +var ( + mapPatt = regexp.MustCompile(`^\*?map\[([^\]]+)\](.+)$`) + arrayPatt = regexp.MustCompile(`^\*?\[(\d+)\](.+)$`) + slicePatt = regexp.MustCompile(`^\*?\[\](.+)$`) +) + +// discriminatorParseTypeName returns a reflect.Type for the given type name. +func discriminatorParseTypeName( + typeName string, + typeFn DiscriminatorToTypeFunc) (reflect.Type, error) { + + // Check to see if the type is an array, map, or slice. + var ( + aln = -1 // array length + etn string // map or slice element type name + ktn string // map key type name + ) + if m := arrayPatt.FindStringSubmatch(typeName); len(m) > 0 { + i, err := strconv.Atoi(m[1]) + if err != nil { + return nil, err + } + aln = i + etn = m[2] + } else if m := slicePatt.FindStringSubmatch(typeName); len(m) > 0 { + etn = m[1] + } else if m := mapPatt.FindStringSubmatch(typeName); len(m) > 0 { + ktn = m[1] + etn = m[2] + } + + // indirectTypeName checks to see if the type name begins with a + // "*" characters. If it does, then the type name sans the "*" + // character is returned along with a true value indicating the + // type is a pointer. Otherwise the original type name is returned + // along with a false value. + indirectTypeName := func(tn string) (string, bool) { + if len(tn) > 1 && tn[0] == '*' { + return tn[1:], true + } + return tn, false + } + + lookupType := func(tn string) (reflect.Type, bool) { + // Get the actual type name and a flag indicating whether the + // type is a pointer. + n, p := indirectTypeName(tn) + + var t reflect.Type + ok := false + // look up the type in the external registry to allow name override. + if typeFn != nil { + t, ok = typeFn(n) + } + if !ok { + // Use the built-in registry if the external registry fails + if t, ok = discriminatorTypeRegistry[n]; !ok { + return nil, false + } + } + // If the type was a pointer then get the type's pointer type. + if p { + t = cachedPointerType(t) + } + return t, true + } + + var t reflect.Type + + if ktn == "" && etn != "" { + et, ok := lookupType(etn) + if !ok { + return nil, fmt.Errorf("json: invalid array/slice element type: %s", etn) + } + if aln > -1 { + // Array + t = reflect.ArrayOf(aln, et) + } else { + // Slice + t = reflect.SliceOf(et) + } + } else if ktn != "" && etn != "" { + // Map + kt, ok := lookupType(ktn) + if !ok { + return nil, fmt.Errorf("json: invalid map key type: %s", ktn) + } + et, ok := lookupType(etn) + if !ok { + return nil, fmt.Errorf("json: invalid map element type: %s", etn) + } + t = reflect.MapOf(kt, et) + } else { + var ok bool + if t, ok = lookupType(typeName); !ok { + return nil, fmt.Errorf("json: invalid discriminator type: %s", typeName) + } + } + + return t, nil +} diff --git a/vendor/github.com/vmware/govmomi/vim25/json/encode.go b/vendor/github.com/vmware/govmomi/vim25/json/encode.go new file mode 100644 index 0000000000..0c8aa202fe --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/encode.go @@ -0,0 +1,1453 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package json implements encoding and decoding of JSON as defined in +// RFC 7159. The mapping between JSON and Go values is described +// in the documentation for the Marshal and Unmarshal functions. +// +// See "JSON and Go" for an introduction to this package: +// https://golang.org/doc/articles/json_and_go.html +package json + +import ( + "bytes" + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. If no MarshalJSON method is present but the +// value implements encoding.TextMarshaler instead, Marshal calls +// its MarshalText method and encodes the result as a JSON string. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and Number values encode as JSON numbers. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// So that the JSON will be safe to embed inside HTML