VMware vSphere Integrated Containers provider (#206)
* Add Virtual Kubelet provider for VIC Initial virtual kubelet provider for VMware VIC. This provider currently handles creating and starting of a pod VM via the VIC portlayer and persona server. Image store handling via the VIC persona server. This provider currently requires the feature/wolfpack branch of VIC. * Added pod stop and delete. Also added node capacity. Added the ability to stop and delete pod VMs via VIC. Also retrieve node capacity information from the VCH. * Cleanup and readme file Some file clean up and added a Readme.md markdown file for the VIC provider. * Cleaned up errors, added function comments, moved operation code 1. Cleaned up error handling. Set standard for creating errors. 2. Added method prototype comments for all interface functions. 3. Moved PodCreator, PodStarter, PodStopper, and PodDeleter to a new folder. * Add mocking code and unit tests for podcache, podcreator, and podstarter Used the unit test framework used in VIC to handle assertions in the provider's unit test. Mocking code generated using OSS project mockery, which is compatible with the testify assertion framework. * Vendored packages for the VIC provider Requires feature/wolfpack branch of VIC and a few specific commit sha of projects used within VIC. * Implementation of POD Stopper and Deleter unit tests (#4) * Updated files for initial PR
This commit is contained in:
137
vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go
generated
vendored
Normal file
137
vendor/github.com/vmware/govmomi/vim25/mo/ancestors.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
// Ancestors returns the entire ancestry tree of a specified managed object.
|
||||
// The return value includes the root node and the specified object itself.
|
||||
func Ancestors(ctx context.Context, rt soap.RoundTripper, pc, obj types.ManagedObjectReference) ([]ManagedEntity, error) {
|
||||
ospec := types.ObjectSpec{
|
||||
Obj: obj,
|
||||
SelectSet: []types.BaseSelectionSpec{
|
||||
&types.TraversalSpec{
|
||||
SelectionSpec: types.SelectionSpec{Name: "traverseParent"},
|
||||
Type: "ManagedEntity",
|
||||
Path: "parent",
|
||||
Skip: types.NewBool(false),
|
||||
SelectSet: []types.BaseSelectionSpec{
|
||||
&types.SelectionSpec{Name: "traverseParent"},
|
||||
},
|
||||
},
|
||||
&types.TraversalSpec{
|
||||
SelectionSpec: types.SelectionSpec{},
|
||||
Type: "VirtualMachine",
|
||||
Path: "parentVApp",
|
||||
Skip: types.NewBool(false),
|
||||
SelectSet: []types.BaseSelectionSpec{
|
||||
&types.SelectionSpec{Name: "traverseParent"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Skip: types.NewBool(false),
|
||||
}
|
||||
|
||||
pspec := []types.PropertySpec{
|
||||
{
|
||||
Type: "ManagedEntity",
|
||||
PathSet: []string{"name", "parent"},
|
||||
},
|
||||
{
|
||||
Type: "VirtualMachine",
|
||||
PathSet: []string{"parentVApp"},
|
||||
},
|
||||
}
|
||||
|
||||
req := types.RetrieveProperties{
|
||||
This: pc,
|
||||
SpecSet: []types.PropertyFilterSpec{
|
||||
{
|
||||
ObjectSet: []types.ObjectSpec{ospec},
|
||||
PropSet: pspec,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var ifaces []interface{}
|
||||
err := RetrievePropertiesForRequest(ctx, rt, req, &ifaces)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out []ManagedEntity
|
||||
|
||||
// Build ancestry tree by iteratively finding a new child.
|
||||
for len(out) < len(ifaces) {
|
||||
var find types.ManagedObjectReference
|
||||
|
||||
if len(out) > 0 {
|
||||
find = out[len(out)-1].Self
|
||||
}
|
||||
|
||||
// Find entity we're looking for given the last entity in the current tree.
|
||||
for _, iface := range ifaces {
|
||||
me := iface.(IsManagedEntity).GetManagedEntity()
|
||||
|
||||
if me.Name == "" {
|
||||
// The types below have their own 'Name' field, so ManagedEntity.Name (me.Name) is empty.
|
||||
// We only hit this case when the 'obj' param is one of these types.
|
||||
// In most cases, 'obj' is a Folder so Name isn't collected in this call.
|
||||
switch x := iface.(type) {
|
||||
case Network:
|
||||
me.Name = x.Name
|
||||
case DistributedVirtualSwitch:
|
||||
me.Name = x.Name
|
||||
case DistributedVirtualPortgroup:
|
||||
me.Name = x.Name
|
||||
case OpaqueNetwork:
|
||||
me.Name = x.Name
|
||||
default:
|
||||
// ManagedEntity always has a Name, if we hit this point we missed a case above.
|
||||
panic(fmt.Sprintf("%#v Name is empty", me.Reference()))
|
||||
}
|
||||
}
|
||||
|
||||
if me.Parent == nil {
|
||||
// Special case for VirtualMachine within VirtualApp,
|
||||
// unlikely to hit this other than via Finder.Element()
|
||||
switch x := iface.(type) {
|
||||
case VirtualMachine:
|
||||
me.Parent = x.ParentVApp
|
||||
}
|
||||
}
|
||||
|
||||
if me.Parent == nil {
|
||||
out = append(out, me)
|
||||
break
|
||||
}
|
||||
|
||||
if *me.Parent == find {
|
||||
out = append(out, me)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
24
vendor/github.com/vmware/govmomi/vim25/mo/entity.go
generated
vendored
Normal file
24
vendor/github.com/vmware/govmomi/vim25/mo/entity.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright (c) 2016 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 mo
|
||||
|
||||
// Entity is the interface that is implemented by all managed objects
|
||||
// that extend ManagedEntity.
|
||||
type Entity interface {
|
||||
Reference
|
||||
Entity() *ManagedEntity
|
||||
}
|
||||
61
vendor/github.com/vmware/govmomi/vim25/mo/extra.go
generated
vendored
Normal file
61
vendor/github.com/vmware/govmomi/vim25/mo/extra.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
type IsManagedEntity interface {
|
||||
GetManagedEntity() ManagedEntity
|
||||
}
|
||||
|
||||
func (m ComputeResource) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m Datacenter) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m Datastore) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m DistributedVirtualSwitch) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m DistributedVirtualPortgroup) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m Folder) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m HostSystem) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m Network) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m ResourcePool) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
|
||||
func (m VirtualMachine) GetManagedEntity() ManagedEntity {
|
||||
return m.ManagedEntity
|
||||
}
|
||||
15
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/cluster_host_property.xml
generated
vendored
Normal file
15
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/cluster_host_property.xml
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RetrievePropertiesResponse xmlns="urn:vim25" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<returnval>
|
||||
<obj type="ClusterComputeResource">domain-c7</obj>
|
||||
<propSet>
|
||||
<name>host</name>
|
||||
<val xsi:type="ArrayOfManagedObjectReference">
|
||||
<ManagedObjectReference type="HostSystem" xsi:type="ManagedObjectReference">host-14</ManagedObjectReference>
|
||||
<ManagedObjectReference type="HostSystem" xsi:type="ManagedObjectReference">host-17</ManagedObjectReference>
|
||||
<ManagedObjectReference type="HostSystem" xsi:type="ManagedObjectReference">host-19</ManagedObjectReference>
|
||||
<ManagedObjectReference type="HostSystem" xsi:type="ManagedObjectReference">host-52</ManagedObjectReference>
|
||||
</val>
|
||||
</propSet>
|
||||
</returnval>
|
||||
</RetrievePropertiesResponse>
|
||||
17
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/hostsystem_list_name_property.xml
generated
vendored
Normal file
17
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/hostsystem_list_name_property.xml
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RetrievePropertiesResponse xmlns="urn:vim25" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<returnval>
|
||||
<obj type="HostSystem">host-10</obj>
|
||||
<propSet>
|
||||
<name>name</name>
|
||||
<val xsi:type="xsd:string">host-01.example.com</val>
|
||||
</propSet>
|
||||
</returnval>
|
||||
<returnval>
|
||||
<obj type="HostSystem">host-30</obj>
|
||||
<propSet>
|
||||
<name>name</name>
|
||||
<val xsi:type="xsd:string">host-02.example.com</val>
|
||||
</propSet>
|
||||
</returnval>
|
||||
</RetrievePropertiesResponse>
|
||||
14
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/nested_property.xml
generated
vendored
Normal file
14
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/nested_property.xml
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RetrievePropertiesResponse xmlns="urn:vim25" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<returnval>
|
||||
<obj type="VirtualMachine">vm-411</obj>
|
||||
<propSet>
|
||||
<name>config.name</name>
|
||||
<val xsi:type="xsd:string">kubernetes-master</val>
|
||||
</propSet>
|
||||
<propSet>
|
||||
<name>config.uuid</name>
|
||||
<val xsi:type="xsd:string">422ec880-ab06-06b4-23f3-beb7a052a4c9</val>
|
||||
</propSet>
|
||||
</returnval>
|
||||
</RetrievePropertiesResponse>
|
||||
42
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/not_authenticated_fault.xml
generated
vendored
Normal file
42
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/not_authenticated_fault.xml
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RetrievePropertiesResponse xmlns="urn:vim25" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<returnval>
|
||||
<obj type="SessionManager">SessionManager</obj>
|
||||
<propSet>
|
||||
<name>defaultLocale</name>
|
||||
<val xsi:type="xsd:string">en</val>
|
||||
</propSet>
|
||||
<propSet>
|
||||
<name>messageLocaleList</name>
|
||||
<val xsi:type="ArrayOfString">
|
||||
<string xsi:type="xsd:string">ja</string>
|
||||
<string xsi:type="xsd:string">zh_CN</string>
|
||||
<string xsi:type="xsd:string">en</string>
|
||||
<string xsi:type="xsd:string">de</string>
|
||||
<string xsi:type="xsd:string">zh_TW</string>
|
||||
<string xsi:type="xsd:string">ko</string>
|
||||
<string xsi:type="xsd:string">fr</string>
|
||||
</val>
|
||||
</propSet>
|
||||
<missingSet>
|
||||
<path>message</path>
|
||||
<fault>
|
||||
<fault xsi:type="NotAuthenticated">
|
||||
<object type="Folder">group-d1</object>
|
||||
<privilegeId>System.View</privilegeId>
|
||||
</fault>
|
||||
<localizedMessage/>
|
||||
</fault>
|
||||
</missingSet>
|
||||
<missingSet>
|
||||
<path>sessionList</path>
|
||||
<fault>
|
||||
<fault xsi:type="NotAuthenticated">
|
||||
<object type="Folder">group-d1</object>
|
||||
<privilegeId>Sessions.TerminateSession</privilegeId>
|
||||
</fault>
|
||||
<localizedMessage/>
|
||||
</fault>
|
||||
</missingSet>
|
||||
</returnval>
|
||||
</RetrievePropertiesResponse>
|
||||
15
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/pointer_property.xml
generated
vendored
Normal file
15
vendor/github.com/vmware/govmomi/vim25/mo/fixtures/pointer_property.xml
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RetrievePropertiesResponse xmlns="urn:vim25" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<returnval>
|
||||
<obj type="VirtualMachine">vm-411</obj>
|
||||
<propSet>
|
||||
<name>config.bootOptions</name>
|
||||
<val xsi:type="VirtualMachineBootOptions">
|
||||
<bootDelay>0</bootDelay>
|
||||
<enterBIOSSetup>false</enterBIOSSetup>
|
||||
<bootRetryEnabled>false</bootRetryEnabled>
|
||||
<bootRetryDelay>10000</bootRetryDelay>
|
||||
</val>
|
||||
</propSet>
|
||||
</returnval>
|
||||
</RetrievePropertiesResponse>
|
||||
1757
vendor/github.com/vmware/govmomi/vim25/mo/mo.go
generated
vendored
Normal file
1757
vendor/github.com/vmware/govmomi/vim25/mo/mo.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
vendor/github.com/vmware/govmomi/vim25/mo/reference.go
generated
vendored
Normal file
26
vendor/github.com/vmware/govmomi/vim25/mo/reference.go
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import "github.com/vmware/govmomi/vim25/types"
|
||||
|
||||
// Reference is the interface that is implemented by all the managed objects
|
||||
// defined in this package. It specifies that these managed objects have a
|
||||
// function that returns the managed object reference to themselves.
|
||||
type Reference interface {
|
||||
Reference() types.ManagedObjectReference
|
||||
}
|
||||
21
vendor/github.com/vmware/govmomi/vim25/mo/registry.go
generated
vendored
Normal file
21
vendor/github.com/vmware/govmomi/vim25/mo/registry.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import "reflect"
|
||||
|
||||
var t = map[string]reflect.Type{}
|
||||
174
vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go
generated
vendored
Normal file
174
vendor/github.com/vmware/govmomi/vim25/mo/retrieve.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
func ignoreMissingProperty(ref types.ManagedObjectReference, p types.MissingProperty) bool {
|
||||
switch ref.Type {
|
||||
case "VirtualMachine":
|
||||
switch p.Path {
|
||||
case "environmentBrowser":
|
||||
// See https://github.com/vmware/govmomi/pull/242
|
||||
return true
|
||||
case "alarmActionsEnabled":
|
||||
// Seen with vApp child VM
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ObjectContentToType loads an ObjectContent value into the value it
|
||||
// represents. If the ObjectContent value has a non-empty 'MissingSet' field,
|
||||
// it returns the first fault it finds there as error. If the 'MissingSet'
|
||||
// field is empty, it returns a pointer to a reflect.Value. It handles contain
|
||||
// nested properties, such as 'guest.ipAddress' or 'config.hardware'.
|
||||
func ObjectContentToType(o types.ObjectContent) (interface{}, error) {
|
||||
// Expect no properties in the missing set
|
||||
for _, p := range o.MissingSet {
|
||||
if ignoreMissingProperty(o.Obj, p) {
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, soap.WrapVimFault(p.Fault.Fault)
|
||||
}
|
||||
|
||||
ti := typeInfoForType(o.Obj.Type)
|
||||
v, err := ti.LoadFromObjectContent(o)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.Elem().Interface(), nil
|
||||
}
|
||||
|
||||
// LoadRetrievePropertiesResponse converts the response of a call to
|
||||
// RetrieveProperties to one or more managed objects.
|
||||
func LoadRetrievePropertiesResponse(res *types.RetrievePropertiesResponse, dst interface{}) error {
|
||||
rt := reflect.TypeOf(dst)
|
||||
if rt == nil || rt.Kind() != reflect.Ptr {
|
||||
panic("need pointer")
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(dst).Elem()
|
||||
if !rv.CanSet() {
|
||||
panic("cannot set dst")
|
||||
}
|
||||
|
||||
isSlice := false
|
||||
switch rt.Elem().Kind() {
|
||||
case reflect.Struct:
|
||||
case reflect.Slice:
|
||||
isSlice = true
|
||||
default:
|
||||
panic("unexpected type")
|
||||
}
|
||||
|
||||
if isSlice {
|
||||
for _, p := range res.Returnval {
|
||||
v, err := ObjectContentToType(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vt := reflect.TypeOf(v)
|
||||
|
||||
if !rv.Type().AssignableTo(vt) {
|
||||
// For example: dst is []ManagedEntity, res is []HostSystem
|
||||
if field, ok := vt.FieldByName(rt.Elem().Elem().Name()); ok && field.Anonymous {
|
||||
rv.Set(reflect.Append(rv, reflect.ValueOf(v).FieldByIndex(field.Index)))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
rv.Set(reflect.Append(rv, reflect.ValueOf(v)))
|
||||
}
|
||||
} else {
|
||||
switch len(res.Returnval) {
|
||||
case 0:
|
||||
case 1:
|
||||
v, err := ObjectContentToType(res.Returnval[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vt := reflect.TypeOf(v)
|
||||
|
||||
if !rv.Type().AssignableTo(vt) {
|
||||
// For example: dst is ComputeResource, res is ClusterComputeResource
|
||||
if field, ok := vt.FieldByName(rt.Elem().Name()); ok && field.Anonymous {
|
||||
rv.Set(reflect.ValueOf(v).FieldByIndex(field.Index))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
rv.Set(reflect.ValueOf(v))
|
||||
default:
|
||||
// If dst is not a slice, expect to receive 0 or 1 results
|
||||
panic("more than 1 result")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RetrievePropertiesForRequest calls the RetrieveProperties method with the
|
||||
// specified request and decodes the response struct into the value pointed to
|
||||
// by dst.
|
||||
func RetrievePropertiesForRequest(ctx context.Context, r soap.RoundTripper, req types.RetrieveProperties, dst interface{}) error {
|
||||
res, err := methods.RetrieveProperties(ctx, r, &req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return LoadRetrievePropertiesResponse(res, dst)
|
||||
}
|
||||
|
||||
// RetrieveProperties retrieves the properties of the managed object specified
|
||||
// as obj and decodes the response struct into the value pointed to by dst.
|
||||
func RetrieveProperties(ctx context.Context, r soap.RoundTripper, pc, obj types.ManagedObjectReference, dst interface{}) error {
|
||||
req := types.RetrieveProperties{
|
||||
This: pc,
|
||||
SpecSet: []types.PropertyFilterSpec{
|
||||
{
|
||||
ObjectSet: []types.ObjectSpec{
|
||||
{
|
||||
Obj: obj,
|
||||
Skip: types.NewBool(false),
|
||||
},
|
||||
},
|
||||
PropSet: []types.PropertySpec{
|
||||
{
|
||||
All: types.NewBool(true),
|
||||
Type: obj.Type,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return RetrievePropertiesForRequest(ctx, r, req, dst)
|
||||
}
|
||||
144
vendor/github.com/vmware/govmomi/vim25/mo/retrieve_test.go
generated
vendored
Normal file
144
vendor/github.com/vmware/govmomi/vim25/mo/retrieve_test.go
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/govmomi/vim25/xml"
|
||||
)
|
||||
|
||||
func load(name string) *types.RetrievePropertiesResponse {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
var b types.RetrievePropertiesResponse
|
||||
|
||||
dec := xml.NewDecoder(f)
|
||||
dec.TypeFunc = types.TypeFunc()
|
||||
if err := dec.Decode(&b); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &b
|
||||
}
|
||||
|
||||
func TestNotAuthenticatedFault(t *testing.T) {
|
||||
var s SessionManager
|
||||
|
||||
err := LoadRetrievePropertiesResponse(load("fixtures/not_authenticated_fault.xml"), &s)
|
||||
if !soap.IsVimFault(err) {
|
||||
t.Errorf("Expected IsVimFault")
|
||||
}
|
||||
|
||||
fault := soap.ToVimFault(err).(*types.NotAuthenticated)
|
||||
if fault.PrivilegeId != "System.View" {
|
||||
t.Errorf("Expected first fault to be returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNestedProperty(t *testing.T) {
|
||||
var vm VirtualMachine
|
||||
|
||||
err := LoadRetrievePropertiesResponse(load("fixtures/nested_property.xml"), &vm)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %s", err)
|
||||
}
|
||||
|
||||
self := types.ManagedObjectReference{
|
||||
Type: "VirtualMachine",
|
||||
Value: "vm-411",
|
||||
}
|
||||
|
||||
if vm.Self != self {
|
||||
t.Fatalf("Expected vm.Self to be set")
|
||||
}
|
||||
|
||||
if vm.Config == nil {
|
||||
t.Fatalf("Expected vm.Config to be set")
|
||||
}
|
||||
|
||||
if vm.Config.Name != "kubernetes-master" {
|
||||
t.Errorf("Got: %s", vm.Config.Name)
|
||||
}
|
||||
|
||||
if vm.Config.Uuid != "422ec880-ab06-06b4-23f3-beb7a052a4c9" {
|
||||
t.Errorf("Got: %s", vm.Config.Uuid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointerProperty(t *testing.T) {
|
||||
var vm VirtualMachine
|
||||
|
||||
err := LoadRetrievePropertiesResponse(load("fixtures/pointer_property.xml"), &vm)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %s", err)
|
||||
}
|
||||
|
||||
if vm.Config == nil {
|
||||
t.Fatalf("Expected vm.Config to be set")
|
||||
}
|
||||
|
||||
if vm.Config.BootOptions == nil {
|
||||
t.Fatalf("Expected vm.Config.BootOptions to be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmbeddedTypeProperty(t *testing.T) {
|
||||
// Test that we avoid in this case:
|
||||
// panic: reflect.Set: value of type mo.ClusterComputeResource is not assignable to type mo.ComputeResource
|
||||
var cr ComputeResource
|
||||
|
||||
err := LoadRetrievePropertiesResponse(load("fixtures/cluster_host_property.xml"), &cr)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %s", err)
|
||||
}
|
||||
|
||||
if len(cr.Host) != 4 {
|
||||
t.Fatalf("Expected cr.Host to be set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmbeddedTypePropertySlice(t *testing.T) {
|
||||
var me []ManagedEntity
|
||||
|
||||
err := LoadRetrievePropertiesResponse(load("fixtures/hostsystem_list_name_property.xml"), &me)
|
||||
if err != nil {
|
||||
t.Fatalf("Expected no error, got: %s", err)
|
||||
}
|
||||
|
||||
if len(me) != 2 {
|
||||
t.Fatalf("Expected 2 elements")
|
||||
}
|
||||
|
||||
for _, m := range me {
|
||||
if m.Name == "" {
|
||||
t.Fatal("Expected Name field to be set")
|
||||
}
|
||||
}
|
||||
|
||||
if me[0].Name == me[1].Name {
|
||||
t.Fatal("Name fields should not be the same")
|
||||
}
|
||||
}
|
||||
247
vendor/github.com/vmware/govmomi/vim25/mo/type_info.go
generated
vendored
Normal file
247
vendor/github.com/vmware/govmomi/vim25/mo/type_info.go
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
)
|
||||
|
||||
type typeInfo struct {
|
||||
typ reflect.Type
|
||||
|
||||
// Field indices of "Self" field.
|
||||
self []int
|
||||
|
||||
// Map property names to field indices.
|
||||
props map[string][]int
|
||||
}
|
||||
|
||||
var typeInfoLock sync.RWMutex
|
||||
var typeInfoMap = make(map[string]*typeInfo)
|
||||
|
||||
func typeInfoForType(tname string) *typeInfo {
|
||||
typeInfoLock.RLock()
|
||||
ti, ok := typeInfoMap[tname]
|
||||
typeInfoLock.RUnlock()
|
||||
|
||||
if ok {
|
||||
return ti
|
||||
}
|
||||
|
||||
// Create new typeInfo for type.
|
||||
if typ, ok := t[tname]; !ok {
|
||||
panic("unknown type: " + tname)
|
||||
} else {
|
||||
// Multiple routines may race to set it, but the result is the same.
|
||||
typeInfoLock.Lock()
|
||||
ti = newTypeInfo(typ)
|
||||
typeInfoMap[tname] = ti
|
||||
typeInfoLock.Unlock()
|
||||
}
|
||||
|
||||
return ti
|
||||
}
|
||||
|
||||
func newTypeInfo(typ reflect.Type) *typeInfo {
|
||||
t := typeInfo{
|
||||
typ: typ,
|
||||
props: make(map[string][]int),
|
||||
}
|
||||
|
||||
t.build(typ, "", []int{})
|
||||
|
||||
return &t
|
||||
}
|
||||
|
||||
var managedObjectRefType = reflect.TypeOf((*types.ManagedObjectReference)(nil)).Elem()
|
||||
|
||||
func buildName(fn string, f reflect.StructField) string {
|
||||
if fn != "" {
|
||||
fn += "."
|
||||
}
|
||||
|
||||
motag := f.Tag.Get("mo")
|
||||
if motag != "" {
|
||||
return fn + motag
|
||||
}
|
||||
|
||||
xmltag := f.Tag.Get("xml")
|
||||
if xmltag != "" {
|
||||
tokens := strings.Split(xmltag, ",")
|
||||
if tokens[0] != "" {
|
||||
return fn + tokens[0]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (t *typeInfo) build(typ reflect.Type, fn string, fi []int) {
|
||||
if typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
|
||||
if typ.Kind() != reflect.Struct {
|
||||
panic("need struct")
|
||||
}
|
||||
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
f := typ.Field(i)
|
||||
ftyp := f.Type
|
||||
|
||||
// Copy field indices so they can be passed along.
|
||||
fic := make([]int, len(fi)+1)
|
||||
copy(fic, fi)
|
||||
fic[len(fi)] = i
|
||||
|
||||
// Recurse into embedded field.
|
||||
if f.Anonymous {
|
||||
t.build(ftyp, fn, fic)
|
||||
continue
|
||||
}
|
||||
|
||||
// Top level type has a "Self" field.
|
||||
if f.Name == "Self" && ftyp == managedObjectRefType {
|
||||
t.self = fic
|
||||
continue
|
||||
}
|
||||
|
||||
fnc := buildName(fn, f)
|
||||
if fnc == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
t.props[fnc] = fic
|
||||
|
||||
// Dereference pointer.
|
||||
if ftyp.Kind() == reflect.Ptr {
|
||||
ftyp = ftyp.Elem()
|
||||
}
|
||||
|
||||
// Slices are not addressable by `foo.bar.qux`.
|
||||
if ftyp.Kind() == reflect.Slice {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip the managed reference type.
|
||||
if ftyp == managedObjectRefType {
|
||||
continue
|
||||
}
|
||||
|
||||
// Recurse into structs.
|
||||
if ftyp.Kind() == reflect.Struct {
|
||||
t.build(ftyp, fnc, fic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assignValue assignes a value 'pv' to the struct pointed to by 'val', given a
|
||||
// slice of field indices. It recurses into the struct until it finds the field
|
||||
// specified by the indices. It creates new values for pointer types where
|
||||
// needed.
|
||||
func assignValue(val reflect.Value, fi []int, pv reflect.Value) {
|
||||
// Create new value if necessary.
|
||||
if val.Kind() == reflect.Ptr {
|
||||
if val.IsNil() {
|
||||
val.Set(reflect.New(val.Type().Elem()))
|
||||
}
|
||||
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
rv := val.Field(fi[0])
|
||||
fi = fi[1:]
|
||||
if len(fi) == 0 {
|
||||
rt := rv.Type()
|
||||
pt := pv.Type()
|
||||
|
||||
// If type is a pointer, create new instance of type.
|
||||
if rt.Kind() == reflect.Ptr {
|
||||
rv.Set(reflect.New(rt.Elem()))
|
||||
rv = rv.Elem()
|
||||
rt = rv.Type()
|
||||
}
|
||||
|
||||
// If type is an interface, check if pv implements it.
|
||||
if rt.Kind() == reflect.Interface && !pt.Implements(rt) {
|
||||
// Check if pointer to pv implements it.
|
||||
if reflect.PtrTo(pt).Implements(rt) {
|
||||
npv := reflect.New(pt)
|
||||
npv.Elem().Set(pv)
|
||||
pv = npv
|
||||
pt = pv.Type()
|
||||
} else {
|
||||
panic(fmt.Sprintf("type %s doesn't implement %s", pt.Name(), rt.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
if pt.AssignableTo(rt) {
|
||||
rv.Set(pv)
|
||||
} else if rt.ConvertibleTo(pt) {
|
||||
rv.Set(pv.Convert(rt))
|
||||
} else {
|
||||
panic(fmt.Sprintf("cannot assign %s (%s) to %s (%s)", rt.Name(), rt.Kind(), pt.Name(), pt.Kind()))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
assignValue(rv, fi, pv)
|
||||
}
|
||||
|
||||
var arrayOfRegexp = regexp.MustCompile("ArrayOf(.*)$")
|
||||
|
||||
func anyTypeToValue(t interface{}) reflect.Value {
|
||||
rt := reflect.TypeOf(t)
|
||||
rv := reflect.ValueOf(t)
|
||||
|
||||
// Dereference if ArrayOfXYZ type
|
||||
m := arrayOfRegexp.FindStringSubmatch(rt.Name())
|
||||
if len(m) > 0 {
|
||||
// ArrayOfXYZ type has single field named XYZ
|
||||
rv = rv.FieldByName(m[1])
|
||||
if !rv.IsValid() {
|
||||
panic(fmt.Sprintf("expected %s type to have field %s", m[0], m[1]))
|
||||
}
|
||||
}
|
||||
|
||||
return rv
|
||||
}
|
||||
|
||||
// LoadObjectFromContent loads properties from the 'PropSet' field in the
|
||||
// specified ObjectContent value into the value it represents, which is
|
||||
// returned as a reflect.Value.
|
||||
func (t *typeInfo) LoadFromObjectContent(o types.ObjectContent) (reflect.Value, error) {
|
||||
v := reflect.New(t.typ)
|
||||
assignValue(v, t.self, reflect.ValueOf(o.Obj))
|
||||
|
||||
for _, p := range o.PropSet {
|
||||
rv, ok := t.props[p.Name]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
assignValue(v, rv, anyTypeToValue(p.Val))
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
37
vendor/github.com/vmware/govmomi/vim25/mo/type_info_test.go
generated
vendored
Normal file
37
vendor/github.com/vmware/govmomi/vim25/mo/type_info_test.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
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 mo
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestLoadAll(*testing.T) {
|
||||
for _, typ := range t {
|
||||
newTypeInfo(typ)
|
||||
}
|
||||
}
|
||||
|
||||
// The virtual machine managed object has about 500 nested properties.
|
||||
// It's likely to be indicative of the function's performance in general.
|
||||
func BenchmarkLoadVirtualMachine(b *testing.B) {
|
||||
vmtyp := reflect.TypeOf((*VirtualMachine)(nil)).Elem()
|
||||
for i := 0; i < b.N; i++ {
|
||||
newTypeInfo(vmtyp)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user