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:
576
vendor/github.com/vmware/vic/cmd/vic-machine/converter/converter.go
generated
vendored
Normal file
576
vendor/github.com/vmware/vic/cmd/vic-machine/converter/converter.go
generated
vendored
Normal file
@@ -0,0 +1,576 @@
|
||||
// Copyright 2017 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 converter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/vic/cmd/vic-machine/common"
|
||||
"github.com/vmware/vic/lib/config/executor"
|
||||
"github.com/vmware/vic/lib/install/data"
|
||||
"github.com/vmware/vic/pkg/ip"
|
||||
viclog "github.com/vmware/vic/pkg/log"
|
||||
)
|
||||
|
||||
const (
|
||||
cmdTag = "cmd"
|
||||
labelTag = "label"
|
||||
parentTagValue = "parent"
|
||||
|
||||
optionSeparator = "-"
|
||||
|
||||
keyAfterValueLabel = "value-key"
|
||||
valueAfterKeyLabel = "key-value"
|
||||
)
|
||||
|
||||
var (
|
||||
kindConverters = make(map[reflect.Kind]converter)
|
||||
typeConverters = make(map[string]converter)
|
||||
labelHandlers = make(map[string]labelConverter)
|
||||
)
|
||||
|
||||
var log = &logrus.Logger{
|
||||
Out: os.Stderr,
|
||||
// We're using our own text formatter to skip the \n and \t escaping logrus
|
||||
// was doing on non TTY Out (we redirect to a file) descriptors.
|
||||
Formatter: viclog.NewTextFormatter(),
|
||||
Hooks: make(logrus.LevelHooks),
|
||||
Level: logrus.InfoLevel,
|
||||
}
|
||||
|
||||
type converter func(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error
|
||||
type labelConverter func(dest map[string][]string, key string) error
|
||||
|
||||
func init() {
|
||||
kindConverters[reflect.Struct] = convertStruct
|
||||
kindConverters[reflect.Slice] = convertSlice
|
||||
kindConverters[reflect.Map] = convertMap
|
||||
kindConverters[reflect.String] = convertString
|
||||
kindConverters[reflect.Ptr] = convertPtr
|
||||
kindConverters[reflect.Int] = convertPrimitive
|
||||
kindConverters[reflect.Int8] = convertPrimitive
|
||||
kindConverters[reflect.Int16] = convertPrimitive
|
||||
kindConverters[reflect.Int32] = convertPrimitive
|
||||
kindConverters[reflect.Int64] = convertPrimitive
|
||||
kindConverters[reflect.Bool] = convertPrimitive
|
||||
kindConverters[reflect.Float32] = convertPrimitive
|
||||
kindConverters[reflect.Float64] = convertPrimitive
|
||||
|
||||
typeConverters["url.URL"] = convertURL
|
||||
typeConverters["net.IPNet"] = convertIPNet
|
||||
typeConverters["net.IP"] = convertIP
|
||||
typeConverters["ip.Range"] = convertIPRange
|
||||
typeConverters["data.NetworkConfig"] = convertNetwork
|
||||
typeConverters["common.ContainerNetworks"] = convertContainerNetworks
|
||||
typeConverters["executor.TrustLevel"] = convertTrustLevel
|
||||
typeConverters["types.SharesInfo"] = convertShares
|
||||
|
||||
labelHandlers[keyAfterValueLabel] = keyAfterValueLabelHandler
|
||||
labelHandlers[valueAfterKeyLabel] = valueAfterKeyLabelHandler
|
||||
}
|
||||
|
||||
func EnableLog() {
|
||||
log.Level = logrus.DebugLevel
|
||||
}
|
||||
|
||||
func DisableLog() {
|
||||
log.Level = logrus.InfoLevel
|
||||
}
|
||||
|
||||
// DataToOption convert data.Data structure to vic-machine create command options based on tags defined in data.Data structure
|
||||
// Note: need to make sure the tags are consistent with command line option name
|
||||
func DataToOption(data *data.Data) (map[string][]string, error) {
|
||||
result := make(map[string][]string)
|
||||
|
||||
if data == nil {
|
||||
return result, nil
|
||||
}
|
||||
err := convert(reflect.ValueOf(data), "", "", result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func convert(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
t := src.Type().String()
|
||||
if converter, ok := typeConverters[t]; ok {
|
||||
return converter(src, prefix, tags, dest)
|
||||
|
||||
}
|
||||
if converter, ok := kindConverters[src.Kind()]; ok {
|
||||
return converter(src, prefix, tags, dest)
|
||||
}
|
||||
log.Debugf("Skipping unsupported field, interface: %#v, kind %s", src, src.Kind())
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertPtr(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
if src.IsNil() {
|
||||
// no need to attempt anything
|
||||
return nil
|
||||
}
|
||||
return convert(src.Elem(), prefix, tags, dest)
|
||||
}
|
||||
|
||||
func convertStruct(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertStruct: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
// iterate through every field in the struct
|
||||
for i := 0; i < src.NumField(); i++ {
|
||||
field := src.Field(i)
|
||||
// get field key, and keep going even if the attribute key is empty, to make sure children attribute is not missing
|
||||
tags := src.Type().Field(i).Tag
|
||||
key := calculateKey(tags, prefix)
|
||||
if err := convert(field, key, tags, dest); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if field.Kind() == reflect.Map {
|
||||
// label handler is invoked in map converter
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertSlice(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertSlice: prefix: %s, src: %s", prefix, src)
|
||||
|
||||
length := src.Len()
|
||||
if length == 0 {
|
||||
log.Debug("Skipping empty slice")
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
if err := convert(src.Index(i), prefix, tags, dest); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertMap(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertMap: prefix: %s, src: %s", prefix, src)
|
||||
|
||||
// iterate over keys and recurse
|
||||
mkeys := src.MapKeys()
|
||||
length := len(mkeys)
|
||||
if length == 0 {
|
||||
log.Debug("Skipping empty map")
|
||||
return nil
|
||||
}
|
||||
|
||||
handler, hasHandler := labelHandlers[tags.Get(labelTag)]
|
||||
// use tempMap to avoid duplicate processing
|
||||
for _, pkey := range src.MapKeys() {
|
||||
tempMap := make(map[string][]string)
|
||||
if pkey.Kind() != reflect.String {
|
||||
log.Errorf("Unsupported map key type interface: %s, kind %s", src, src.Kind())
|
||||
continue
|
||||
}
|
||||
if !hasHandler {
|
||||
if err := convert(src.MapIndex(pkey), prefix, tags, dest); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := convert(src.MapIndex(pkey), prefix, tags, tempMap); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := handler(tempMap, pkey.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range tempMap {
|
||||
addValues(dest, k, v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// keyAfterValueLabelHandler will add the map key as label after the value,
|
||||
// e.g. change from datastore/path to datastore/path:default
|
||||
func keyAfterValueLabelHandler(dest map[string][]string, pkey string) error {
|
||||
log.Debugf("keyAfterValueLabelHandler: map key: %s, map: %#v", pkey, dest)
|
||||
|
||||
for _, values := range dest {
|
||||
for i := range values {
|
||||
values[i] = fmt.Sprintf("%s:%s", values[i], pkey)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// valueAfterKeyLabelHandler will add the map key as label before the value,
|
||||
// e.g. change from 10.10.10.0/24 to management:10.10.10.0/24
|
||||
func valueAfterKeyLabelHandler(dest map[string][]string, pkey string) error {
|
||||
log.Debugf("valueAfterKeyLabelHandler: map key: %s, map: %#v", pkey, dest)
|
||||
|
||||
for _, values := range dest {
|
||||
for i := range values {
|
||||
values[i] = fmt.Sprintf("%s:%s", pkey, values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// calculateKey generate key as prefix-tag. if any one is empty, return the other
|
||||
func calculateKey(tags reflect.StructTag, prefix string) string {
|
||||
tag := tags.Get(cmdTag)
|
||||
if tag == "" {
|
||||
return prefix
|
||||
}
|
||||
if tag == parentTagValue && prefix == "" {
|
||||
return ""
|
||||
}
|
||||
if tag == parentTagValue && prefix != "" {
|
||||
// for this tag, use parent name only
|
||||
return prefix
|
||||
}
|
||||
if prefix == "" {
|
||||
return tag
|
||||
}
|
||||
return fmt.Sprintf("%s%s%s", prefix, optionSeparator, tag)
|
||||
}
|
||||
|
||||
func convertURL(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertURL: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
u, ok := src.Interface().(url.URL)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not URL"))
|
||||
}
|
||||
v := u.String()
|
||||
if u.Scheme == "" {
|
||||
if u.Path == "" {
|
||||
v = u.Host
|
||||
} else if u.Host == "" {
|
||||
v = u.Path
|
||||
} else {
|
||||
v = fmt.Sprintf("%s/%s", u.Host, u.Path)
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertIPNet(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertIPNet: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ipNet, ok := src.Interface().(net.IPNet)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not IPNet"))
|
||||
}
|
||||
if ip.IsUnspecifiedSubnet(&ipNet) {
|
||||
return nil
|
||||
}
|
||||
v := ipNet.String()
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertIP(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertIP: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ipAddr, ok := src.Interface().(net.IP)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not IP"))
|
||||
}
|
||||
if ip.IsUnspecifiedIP(ipAddr) {
|
||||
return nil
|
||||
}
|
||||
v := ipAddr.String()
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertTrustLevel(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertTrustLevel: prefix: %s, src: %s", prefix, src.String())
|
||||
trustLevel, ok := src.Interface().(executor.TrustLevel)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not TrustLevel"))
|
||||
}
|
||||
if trustLevel == executor.Unspecified {
|
||||
return nil
|
||||
}
|
||||
v := trustLevel.String()
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertIPRange(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertIPRange: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
ipRange, ok := src.Interface().(ip.Range)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not ip range"))
|
||||
}
|
||||
v := ipRange.String()
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertString(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertString: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := src.String()
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertPrimitive(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertPrimitive: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := ""
|
||||
switch src.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if src.Int() == 0 {
|
||||
return nil
|
||||
}
|
||||
v = strconv.FormatInt(src.Int(), 10)
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if src.Uint() == 0 {
|
||||
return nil
|
||||
}
|
||||
v = strconv.FormatUint(src.Uint(), 10)
|
||||
case reflect.Bool:
|
||||
if !src.Bool() {
|
||||
return nil
|
||||
}
|
||||
v = strconv.FormatBool(src.Bool())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if src.Float() == 0 {
|
||||
return nil
|
||||
}
|
||||
v = strconv.FormatFloat(src.Float(), 'E', -1, 64)
|
||||
default:
|
||||
panic(fmt.Sprintf("%s is not supported type", src.Kind()))
|
||||
}
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// convertNetwork will merge destination and gateway to one option with format: 192.168.3.0/16,192.168.128.0/16:192.168.2.1
|
||||
// after that, convertStruct is called for left conversion
|
||||
func convertNetwork(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertNetwork: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
network, ok := src.Interface().(data.NetworkConfig)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not NetworkConfig"))
|
||||
}
|
||||
if !network.IsSet() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(network.Destinations) > 0 || !ip.Empty(network.Gateway) {
|
||||
destination := ""
|
||||
if len(network.Destinations) > 0 {
|
||||
for _, d := range network.Destinations {
|
||||
destination = fmt.Sprintf("%s,%s", destination, d.String())
|
||||
}
|
||||
destination = strings.TrimLeft(destination, ",")
|
||||
}
|
||||
gateway := network.Gateway.IP.String()
|
||||
tag := "cmd:\"gateway\""
|
||||
key := calculateKey(reflect.StructTag(tag), prefix)
|
||||
if destination != "" {
|
||||
addValue(dest, key, fmt.Sprintf("%s:%s", destination, gateway))
|
||||
} else {
|
||||
addValue(dest, key, gateway)
|
||||
}
|
||||
}
|
||||
return convertStruct(reflect.ValueOf(network), prefix, tags, dest)
|
||||
}
|
||||
|
||||
func convertShares(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertShares: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
shares, ok := src.Interface().(types.SharesInfo)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not SharesInfo"))
|
||||
}
|
||||
|
||||
v := ""
|
||||
switch shares.Level {
|
||||
case types.SharesLevelCustom:
|
||||
v = fmt.Sprintf("%v", shares.Shares)
|
||||
case types.SharesLevelNormal:
|
||||
return nil
|
||||
default:
|
||||
v = string(shares.Level)
|
||||
}
|
||||
|
||||
log.Debugf("%s=%s", prefix, v)
|
||||
|
||||
addValue(dest, prefix, v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// convertContainerNetworks will switch the map keys in MappedNetworks using value, and replace all keys with the same value in other structure,
|
||||
// cause option is using vsphere network name as key label, but guestinfo is using alias as key for easy to use in portlayer
|
||||
// after that, convertStruct is called for left conversion
|
||||
func convertContainerNetworks(src reflect.Value, prefix string, tags reflect.StructTag, dest map[string][]string) error {
|
||||
log.Debugf("convertContainerNetworks: prefix: %s, src: %s", prefix, src.String())
|
||||
|
||||
if prefix == "" {
|
||||
return nil
|
||||
}
|
||||
if tags.Get(cmdTag) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
networks, ok := src.Interface().(common.ContainerNetworks)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf(src.Type().String() + " is not ContainerNetworks"))
|
||||
}
|
||||
if !networks.IsSet() {
|
||||
return nil
|
||||
}
|
||||
|
||||
newMappedNetworks := make(map[string]string, len(networks.MappedNetworks))
|
||||
for k, v := range networks.MappedNetworks {
|
||||
if k == v {
|
||||
newMappedNetworks[v] = k
|
||||
continue
|
||||
}
|
||||
if dns, ok := networks.MappedNetworksDNS[k]; ok {
|
||||
networks.MappedNetworksDNS[v] = dns
|
||||
delete(networks.MappedNetworksDNS, k)
|
||||
}
|
||||
if gateways, ok := networks.MappedNetworksGateways[k]; ok {
|
||||
networks.MappedNetworksGateways[v] = gateways
|
||||
delete(networks.MappedNetworksGateways, k)
|
||||
}
|
||||
if ipRange, ok := networks.MappedNetworksIPRanges[k]; ok {
|
||||
networks.MappedNetworksIPRanges[v] = ipRange
|
||||
delete(networks.MappedNetworksIPRanges, k)
|
||||
}
|
||||
if firewall, ok := networks.MappedNetworksFirewalls[k]; ok {
|
||||
networks.MappedNetworksFirewalls[v] = firewall
|
||||
delete(networks.MappedNetworksFirewalls, k)
|
||||
}
|
||||
newMappedNetworks[v] = k
|
||||
}
|
||||
networks.MappedNetworks = newMappedNetworks
|
||||
return convertStruct(reflect.ValueOf(networks), prefix, tags, dest)
|
||||
}
|
||||
|
||||
// addValue will append value without duplicates
|
||||
func addValue(dest map[string][]string, key, value string) {
|
||||
slice, _ := dest[key]
|
||||
found := false
|
||||
for _, o := range slice {
|
||||
if o == value {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
slice = append(slice, value)
|
||||
}
|
||||
dest[key] = slice
|
||||
}
|
||||
|
||||
// addValues append new value to existing slice if missing
|
||||
// as this method is called every time the value is appended, the existing slice will be no duplicates
|
||||
func addValues(dest map[string][]string, key string, values []string) {
|
||||
for _, v := range values {
|
||||
addValue(dest, key, v)
|
||||
}
|
||||
}
|
||||
650
vendor/github.com/vmware/vic/cmd/vic-machine/converter/converter_test.go
generated
vendored
Normal file
650
vendor/github.com/vmware/vic/cmd/vic-machine/converter/converter_test.go
generated
vendored
Normal file
@@ -0,0 +1,650 @@
|
||||
// Copyright 2017 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 converter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
"github.com/vmware/vic/lib/config"
|
||||
"github.com/vmware/vic/lib/install/data"
|
||||
"github.com/vmware/vic/lib/install/validate"
|
||||
"github.com/vmware/vic/pkg/vsphere/extraconfig"
|
||||
)
|
||||
|
||||
type testFinder struct {
|
||||
}
|
||||
|
||||
func (f *testFinder) ObjectReference(ctx context.Context, ref types.ManagedObjectReference) (object.Reference, error) {
|
||||
return testObject{
|
||||
Common: object.NewCommon(nil, ref),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type testObject struct {
|
||||
object.Common
|
||||
}
|
||||
|
||||
func (c testObject) Name() string {
|
||||
switch c.Common.Reference().String() {
|
||||
case "DistributedVirtualPortgroup:dvportgroup-357":
|
||||
return "management"
|
||||
case "DistributedVirtualPortgroup:dvportgroup-358":
|
||||
return "vm-network"
|
||||
case "DistributedVirtualPortgroup:dvportgroup-55":
|
||||
return "bridge"
|
||||
case "DistributedVirtualPortgroup:dvportgroup-56":
|
||||
return "external"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
// EnableLog()
|
||||
// trace.Logger.Level = log.DebugLevel
|
||||
|
||||
testInit(t)
|
||||
testConvertImageStore(t)
|
||||
testConvertVolumeStore(t)
|
||||
testConvertVCHName(t)
|
||||
testConvertTarget(t)
|
||||
testConvertOps(t)
|
||||
testConvertBaseImageSize(t)
|
||||
testConvertPublicNetwork(t)
|
||||
testConvertClientNetwork(t)
|
||||
testConvertMgmtNetwork(t)
|
||||
testGuestinfo(t)
|
||||
testConvertSharesInfo(t)
|
||||
}
|
||||
|
||||
func testInit(t *testing.T) {
|
||||
var ok bool
|
||||
_, ok = kindConverters[reflect.Struct]
|
||||
assert.True(t, ok, fmt.Sprintf("Struct converter is not found"))
|
||||
_, ok = kindConverters[reflect.Slice]
|
||||
assert.True(t, ok, fmt.Sprintf("Slice converter is not found"))
|
||||
_, ok = kindConverters[reflect.Map]
|
||||
assert.True(t, ok, fmt.Sprintf("Map converter is not found"))
|
||||
_, ok = kindConverters[reflect.String]
|
||||
assert.True(t, ok, fmt.Sprintf("String converter is not found"))
|
||||
_, ok = kindConverters[reflect.Ptr]
|
||||
assert.True(t, ok, fmt.Sprintf("Pointer converter is not found"))
|
||||
_, ok = kindConverters[reflect.Int]
|
||||
assert.True(t, ok, fmt.Sprintf("Int converter is not found"))
|
||||
_, ok = kindConverters[reflect.Int8]
|
||||
assert.True(t, ok, fmt.Sprintf("Int8 converter is not found"))
|
||||
_, ok = kindConverters[reflect.Int16]
|
||||
assert.True(t, ok, fmt.Sprintf("Int16 converter is not found"))
|
||||
_, ok = kindConverters[reflect.Int32]
|
||||
assert.True(t, ok, fmt.Sprintf("Int32 converter is not found"))
|
||||
_, ok = kindConverters[reflect.Int64]
|
||||
assert.True(t, ok, fmt.Sprintf("Int64 converter is not found"))
|
||||
_, ok = kindConverters[reflect.Bool]
|
||||
assert.True(t, ok, fmt.Sprintf("Bool converter is not found"))
|
||||
_, ok = kindConverters[reflect.Float32]
|
||||
assert.True(t, ok, fmt.Sprintf("Float32 converter is not found"))
|
||||
_, ok = kindConverters[reflect.Float64]
|
||||
assert.True(t, ok, fmt.Sprintf("Float64 converter is not found"))
|
||||
|
||||
_, ok = typeConverters["url.URL"]
|
||||
assert.True(t, ok, fmt.Sprintf("url.URL converter is not found"))
|
||||
_, ok = typeConverters["net.IPNet"]
|
||||
assert.True(t, ok, fmt.Sprintf("net.IPNet converter is not found"))
|
||||
_, ok = typeConverters["net.IP"]
|
||||
assert.True(t, ok, fmt.Sprintf("net.IP converter is not found"))
|
||||
_, ok = typeConverters["ip.Range"]
|
||||
assert.True(t, ok, fmt.Sprintf("ip.Range converter is not found"))
|
||||
_, ok = typeConverters["data.NetworkConfig"]
|
||||
assert.True(t, ok, fmt.Sprintf("data.NetworkConfig converter is not found"))
|
||||
_, ok = typeConverters["common.ContainerNetworks"]
|
||||
assert.True(t, ok, fmt.Sprintf("common.ContainerNetworks converter is not found"))
|
||||
|
||||
_, ok = labelHandlers[keyAfterValueLabel]
|
||||
assert.True(t, ok, fmt.Sprintf("value-key handler is not found"))
|
||||
_, ok = labelHandlers[valueAfterKeyLabel]
|
||||
assert.True(t, ok, fmt.Sprintf("key-value handler is not found"))
|
||||
}
|
||||
|
||||
func testConvertImageStore(t *testing.T) {
|
||||
data := data.NewData()
|
||||
data.ImageDatastorePath = "ds://vsan/path"
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 1, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "ds://vsan/path", options["image-store"][0], "not expected image-store option")
|
||||
}
|
||||
|
||||
func testConvertVolumeStore(t *testing.T) {
|
||||
tests := []struct {
|
||||
in map[string]*url.URL
|
||||
out []string
|
||||
}{
|
||||
{
|
||||
in: map[string]*url.URL{
|
||||
"default": {
|
||||
Scheme: "ds",
|
||||
Host: "vsan",
|
||||
Path: "path/volume",
|
||||
},
|
||||
|
||||
"noSchema": {
|
||||
Host: "vsan",
|
||||
Path: "path1",
|
||||
},
|
||||
},
|
||||
out: []string{
|
||||
"ds://vsan/path/volume:default",
|
||||
"vsan/path1:noSchema",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
data := data.NewData()
|
||||
data.VolumeLocations = test.in
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
|
||||
assert.Equal(t, 1, len(options), "should not have other option generated")
|
||||
vols := options["volume-store"]
|
||||
assert.Equal(t, len(test.out), len(vols), "not expected length")
|
||||
for _, store := range test.out {
|
||||
found := false
|
||||
for _, actual := range vols {
|
||||
if actual == store {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, fmt.Sprintf("%s is not created", store))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testConvertVCHName(t *testing.T) {
|
||||
data := data.NewData()
|
||||
data.DisplayName = "vch1"
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 1, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "vch1", options["name"][0], "not expected name option")
|
||||
}
|
||||
|
||||
func testConvertTarget(t *testing.T) {
|
||||
data := data.NewData()
|
||||
data.Target.URL, _ = url.Parse("1.1.1.1")
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 1, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "1.1.1.1", options["target"][0], "not expected target option")
|
||||
}
|
||||
|
||||
func testConvertOps(t *testing.T) {
|
||||
data := data.NewData()
|
||||
adminUser := "admin"
|
||||
data.OpsCredentials.OpsUser = &adminUser
|
||||
pass := "password"
|
||||
data.OpsCredentials.OpsPassword = &pass
|
||||
data.Thumbprint = "uuidstring"
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(options), "should not have other option generated")
|
||||
assert.Equal(t, *data.OpsCredentials.OpsUser, options["ops-user"][0], "not expected ops-user option")
|
||||
assert.Equal(t, data.Thumbprint, options["thumbprint"][0], "not expected thumbprint option")
|
||||
}
|
||||
|
||||
func testConvertBaseImageSize(t *testing.T) {
|
||||
data := data.NewData()
|
||||
data.ScratchSize = "8GB"
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 1, len(options), "should not have other option generated")
|
||||
assert.Equal(t, data.ScratchSize, options["base-image-size"][0], "not expected base-image-size option")
|
||||
}
|
||||
|
||||
func testConvertBridgeNetwork(t *testing.T) {
|
||||
_, ipnet, _ := net.ParseCIDR("172.16.0.0/12")
|
||||
|
||||
data := data.NewData()
|
||||
data.BridgeIPRange = ipnet
|
||||
data.BridgeNetworkName = "portgroup1"
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 2, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "172.16.0.0/12", options["bridge-network-range"][0], "not expected bridge-network-range option")
|
||||
assert.Equal(t, data.BridgeNetworkName, options["bridge-network"][0], "not expected bridge-network option")
|
||||
}
|
||||
|
||||
func testConvertPublicNetwork(t *testing.T) {
|
||||
gwIP := net.ParseIP("172.16.0.1")
|
||||
_, destination, _ := net.ParseCIDR("172.16.0.0/12")
|
||||
ip, ipNet, _ := net.ParseCIDR("172.16.0.2/12")
|
||||
|
||||
data := data.NewData()
|
||||
data.PublicNetwork.Name = "public"
|
||||
data.PublicNetwork.Gateway.IP = gwIP
|
||||
data.PublicNetwork.Gateway.Mask = ipNet.Mask
|
||||
data.PublicNetwork.IP.IP = ip
|
||||
data.PublicNetwork.IP.Mask = ipNet.Mask
|
||||
data.PublicNetwork.Destinations = append(data.PublicNetwork.Destinations, *destination)
|
||||
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 3, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "172.16.0.0/12:172.16.0.1", options["public-network-gateway"][0], "not expected public-network-gateway option")
|
||||
assert.Equal(t, "172.16.0.2/12", options["public-network-ip"][0], "not expected public-network-ip option")
|
||||
}
|
||||
|
||||
func testConvertClientNetwork(t *testing.T) {
|
||||
gwIP := net.ParseIP("172.16.0.1")
|
||||
_, destination, _ := net.ParseCIDR("172.16.0.0/12")
|
||||
ip, ipNet, _ := net.ParseCIDR("172.16.0.2/12")
|
||||
|
||||
data := data.NewData()
|
||||
data.ClientNetwork.Name = "public"
|
||||
data.ClientNetwork.Gateway.IP = gwIP
|
||||
data.ClientNetwork.Gateway.Mask = ipNet.Mask
|
||||
data.ClientNetwork.IP.IP = ip
|
||||
data.ClientNetwork.IP.Mask = ipNet.Mask
|
||||
data.ClientNetwork.Destinations = append(data.ClientNetwork.Destinations, *destination)
|
||||
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 3, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "172.16.0.0/12:172.16.0.1", options["client-network-gateway"][0], "not expected client-network-gateway option")
|
||||
assert.Equal(t, "172.16.0.2/12", options["client-network-ip"][0], "not expected client-network-ip option")
|
||||
}
|
||||
|
||||
func testConvertMgmtNetwork(t *testing.T) {
|
||||
gwIP := net.ParseIP("172.16.0.1")
|
||||
_, destination, _ := net.ParseCIDR("172.16.0.0/12")
|
||||
ip, ipNet, _ := net.ParseCIDR("172.16.0.2/12")
|
||||
|
||||
data := data.NewData()
|
||||
data.ManagementNetwork.Name = "public"
|
||||
data.ManagementNetwork.Gateway.IP = gwIP
|
||||
data.ManagementNetwork.Gateway.Mask = ipNet.Mask
|
||||
data.ManagementNetwork.IP.IP = ip
|
||||
data.ManagementNetwork.IP.Mask = ipNet.Mask
|
||||
data.ManagementNetwork.Destinations = append(data.ManagementNetwork.Destinations, *destination)
|
||||
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 3, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "172.16.0.0/12:172.16.0.1", options["management-network-gateway"][0], "not expected management-network-gateway option")
|
||||
assert.Equal(t, "172.16.0.2/12", options["management-network-ip"][0], "not expected management-network-ip option")
|
||||
}
|
||||
|
||||
func testConvertContainerNetworks(t *testing.T) {
|
||||
gwIP := net.ParseIP("172.16.0.1")
|
||||
_, destination, _ := net.ParseCIDR("172.16.0.0/12")
|
||||
ip, ipNet, _ := net.ParseCIDR("172.16.0.2/12")
|
||||
|
||||
data := data.NewData()
|
||||
data.ManagementNetwork.Name = "public"
|
||||
data.ManagementNetwork.Gateway.IP = gwIP
|
||||
data.ManagementNetwork.Gateway.Mask = ipNet.Mask
|
||||
data.ManagementNetwork.IP.IP = ip
|
||||
data.ManagementNetwork.IP.Mask = ipNet.Mask
|
||||
data.ManagementNetwork.Destinations = append(data.ManagementNetwork.Destinations, *destination)
|
||||
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 3, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "172.16.0.0/12:172.16.0.1", options["management-network-gateway"][0], "not expected management-network-gateway option")
|
||||
assert.Equal(t, "172.16.0.2/12", options["management-network-ip"][0], "not expected management-network-ip option")
|
||||
}
|
||||
|
||||
func testConvertSharesInfo(t *testing.T) {
|
||||
data := data.NewData()
|
||||
cLimit, cReserve := 29300, 1024
|
||||
data.NumCPUs = 2
|
||||
data.VCHCPULimitsMHz = &cLimit
|
||||
data.VCHCPUReservationsMHz = &cReserve
|
||||
data.VCHCPUShares = &types.SharesInfo{
|
||||
Shares: 6000,
|
||||
Level: types.SharesLevelCustom,
|
||||
}
|
||||
mLimit, mReserve := 13144, 1024
|
||||
data.MemoryMB = 4096
|
||||
data.VCHMemoryLimitsMB = &mLimit
|
||||
data.VCHMemoryReservationsMB = &mReserve
|
||||
data.VCHMemoryShares = &types.SharesInfo{
|
||||
Shares: 163840,
|
||||
Level: types.SharesLevelNormal,
|
||||
}
|
||||
|
||||
options, err := DataToOption(data)
|
||||
assert.Empty(t, err)
|
||||
assert.Equal(t, 7, len(options), "should not have other option generated")
|
||||
assert.Equal(t, "2", options["endpoint-cpu"][0], "not expected endpoint-cpu option")
|
||||
assert.Equal(t, "4096", options["endpoint-memory"][0], "not expected endpoint-memory option")
|
||||
assert.Equal(t, "13144", options["memory"][0], "not expected memory option")
|
||||
assert.Equal(t, "1024", options["memory-reservation"][0], "not expected memory-reservation option")
|
||||
assert.Equal(t, "29300", options["cpu"][0], "not expected cpu option")
|
||||
assert.Equal(t, "1024", options["cpu-reservation"][0], "not expected cpu-reservation option")
|
||||
assert.Equal(t, "6000", options["cpu-shares"][0], "not expected cpu-shares option")
|
||||
}
|
||||
|
||||
func testGuestinfo(t *testing.T) {
|
||||
kv := map[string]string{
|
||||
"guestinfo.vice..init.sessions|docker-personality.detail.createtime": "0",
|
||||
"guestinfo.vice./init/sessions|docker-personality/Group": "",
|
||||
"init/networks|client/Common/notes": "",
|
||||
"guestinfo.vice./network/container_networks|vnet/gateway/IP": "AAAAAAAAAAAAAP//CgoKAQ==",
|
||||
"guestinfo.vice./init/sessions|port-layer/tty": "false",
|
||||
"guestinfo.vice..init.networks|bridge.network.type": "bridge",
|
||||
"vmotion.checkpointSVGAPrimarySize": "4194304",
|
||||
"guestinfo.vice./storage/image_stores|0/Host": "vsanDatastore",
|
||||
"guestinfo.vice./init/sessions|vicadmin/stopSignal": "",
|
||||
"guestinfo.vice./network/container_networks|vnet/Common/id": "DistributedVirtualPortgroup:dvportgroup-357",
|
||||
"guestinfo.vice..init.networks|client.network.assigned.dns|1": "CqYBAQ==",
|
||||
"guestinfo.vice..init.sessions|vicadmin.status": "0",
|
||||
"guestinfo.vice./init/networks|bridge/Common/id": "224",
|
||||
"guestinfo.vice./init/networks|bridge/network/Common/id": "DistributedVirtualPortgroup:dvportgroup-55",
|
||||
"guestinfo.vice./init/diagnostics/debug": "3",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/ForceQuery": "false",
|
||||
"guestinfo.vice./init/sessions|docker-personality/active": "true",
|
||||
"guestinfo.vice./container/ComputeResources": "0",
|
||||
"guestinfo.vice..init.networks|client.network.assigned.gateway.Mask": "///gAA==",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/Opaque": "",
|
||||
"guestinfo.vice..init.networks|management.assigned.IP": "CsCoOQ==",
|
||||
"guestinfo.vice./init/sessions|port-layer/common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/stopSignal": "",
|
||||
"init/networks|management/Common/notes": "",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/RawPath": "",
|
||||
"network/container_networks|bridge/Common/notes": "",
|
||||
"guestinfo.vice..network.container_networks|vmnet.type": "external",
|
||||
"guestinfo.vice..init.sessions|docker-personality.detail.stoptime": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/cmd/Dir": "/home/vicadmin",
|
||||
"guestinfo.vice./connect/keepalive": "0",
|
||||
"guestinfo.vice..init.networks|management.network.type": "",
|
||||
"guestinfo.vice./init/sessions|port-layer/common/name": "port-layer",
|
||||
"guestinfo.vice..init.networks|public.network.assigned.dns|1": "CqYBAQ==",
|
||||
"guestinfo.vice./init/sessions|docker-personality/common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/openstdin": "false",
|
||||
"guestinfo.vice./connect/target_thumbprint": "9F:F0:DF:BA:7F:E2:89:F0:98:E4:A6:D1:58:24:68:74:8A:9B:25:6F",
|
||||
"guestinfo.vice..init.networks|public.network.type": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Path": "/sbin/docker-engine-server",
|
||||
"guestinfo.vice..init.createtime": "0",
|
||||
"guestinfo.vice./init/sessions|port-layer/active": "true",
|
||||
"guestinfo.vice./network/container_networks|vnet/pools|0/last": "CgoK/w==",
|
||||
"init/sessions|docker-personality/common/notes": "",
|
||||
"guestinfo.vice..init.diagnostics.resurrections": "0",
|
||||
"guestinfo.vice..init.networks|public.network.assigned.gateway.Mask": "///gAA==",
|
||||
"guestinfo.vice./init/sessions|port-layer/cmd/Dir": "",
|
||||
"guestinfo.vice./network/container_networks|vnet/pools": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/tty": "false",
|
||||
"guestinfo.vice./storage/image_stores|0/RawPath": "",
|
||||
"guestinfo.vice./init/sessions|port-layer/attach": "false",
|
||||
"guestinfo.vice./container/ComputeResources|0/Type": "VirtualApp",
|
||||
"guestinfo.vice./storage/image_stores|0/Scheme": "ds",
|
||||
"guestinfo.vice..init.networks|public.assigned.Mask": "///gAA==",
|
||||
"guestinfo.vice./init/networks|bridge/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./storage/image_stores|0/Path": "91512359-242e-5a30-ba4a-0200360a2e79",
|
||||
"numa.autosize.vcpu.maxPerVirtualNode": "1",
|
||||
"guestinfo.vice./init/version/BuildDate": "2017/05/06@14:16:54",
|
||||
"guestinfo.vice./init/sessions|docker-personality/User": "",
|
||||
"guestinfo.vice..init.networks|client.assigned.Mask": "///gAA==",
|
||||
"guestinfo.vice./init/networks|management/network/Common/id": "DistributedVirtualPortgroup:dvportgroup-56",
|
||||
"guestinfo.vice./connect/target": "https://10.192.171.116",
|
||||
"guestinfo.vice./storage/image_stores|0/RawQuery": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/runblock": "false",
|
||||
"guestinfo.vice..init.networks|management.network.assigned.gateway.IP": "CsC//Q==",
|
||||
"init/networks|management/network/Common/notes": "",
|
||||
"guestinfo.vice./init/version/GitCommit": "65a1889",
|
||||
"guestinfo.vice./init/networks|public/Common/name": "public",
|
||||
"guestinfo.vice./init/version/Version": "v1.1.0-rc3",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/Scheme": "ds",
|
||||
"answer.msg.serial.file.open": "Append",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/Path": "[vsanDatastore] volumes/default",
|
||||
"guestinfo.vice..init.networks|management.network.assigned.dns": "1",
|
||||
"guestinfo.vice./init/networks|public/network/Common/id": "DistributedVirtualPortgroup:dvportgroup-56",
|
||||
"guestinfo.vice./storage/image_stores|0/ForceQuery": "false",
|
||||
"guestinfo.vice./init/imageid": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Env": "3",
|
||||
"guestinfo.vice./init/sessions|docker-personality/common/id": "docker-personality",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/Fragment": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/cmd/Env": "3",
|
||||
"guestinfo.vice./init/sessions|vicadmin/common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/User": "vicadmin",
|
||||
"guestinfo.vice..init.networks|public.network.assigned.dns": "1",
|
||||
"network/container_networks|vnet/Common/notes": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/common/id": "vicadmin",
|
||||
"guestinfo.vice..init.sessions|docker-personality.diagnostics.resurrections": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/cmd/Args~": "/sbin/vicadmin|--dc=vcqaDC|--pool=|--cluster=/vcqaDC/host/cls",
|
||||
"guestinfo.vice./init/networks|public/static": "false",
|
||||
"guestinfo.vice./init/networks|client/network/default": "false",
|
||||
"init/networks|public/network/Common/notes": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/restart": "true",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/Host": "vsanDatastore",
|
||||
"guestinfo.vice./init/networks|bridge/network/Common/name": "bridge",
|
||||
"guestinfo.vice..init.sessions|vicadmin.detail.stoptime": "0",
|
||||
"guestinfo.vice./container/ComputeResources|0/Value": "resgroup-v364",
|
||||
"guestinfo.vice./network/container_networks|vmnet/Common/name": "vmnet",
|
||||
"guestinfo.vice./network/container_networks": "bridge|vmnet|vnet",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Args": "2",
|
||||
"guestinfo.vice./init/networks|bridge/ip/IP": "AAAAAAAAAAAAAP//AAAAAA==",
|
||||
"guestinfo.vice./init/networks|bridge/network/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/RawQuery": "",
|
||||
"guestinfo.vice..init.networks|public.assigned.IP": "CsCoOQ==",
|
||||
"guestinfo.vice./init/networks|bridge/Common/name": "bridge",
|
||||
"guestinfo.vice./init/sessions|port-layer/openstdin": "false",
|
||||
"guestinfo.vice./create_bridge_network": "false",
|
||||
"guestinfo.vice./init/networks|management/Common/id": "192",
|
||||
"guestinfo.vice..init.networks|management.network.assigned.dns|0": "CqLMAQ==",
|
||||
"guestinfo.vice..init.networks|public.network.assigned.dns|0": "CqLMAQ==",
|
||||
"guestinfo.vice..init.sessions|docker-personality.started": "true",
|
||||
"init/networks|public/Common/notes": "",
|
||||
"guestinfo.vice..init.networks|management.network.assigned.dns|1": "CqYBAQ==",
|
||||
"guestinfo.vice./init/sessions|vicadmin/active": "true",
|
||||
"guestinfo.vice./init/networks": "bridge|client|management|public",
|
||||
"guestinfo.vice./init/networks|client/Common/id": "192",
|
||||
"guestinfo.vice./network/container_networks|vnet/Common/ExecutionEnvironment": "",
|
||||
"init/networks|client/network/Common/notes": "",
|
||||
"guestinfo.vice..init.sessions|port-layer.detail.stoptime": "0",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Args~": "/sbin/docker-engine-server|-port=2376|-port-layer-port=2377",
|
||||
"guestinfo.vice..init.sessions|vicadmin.runblock": "false",
|
||||
"guestinfo.vice./init/sessions|port-layer/Group": "",
|
||||
"guestinfo.vice./init/version/PluginVersion": "6",
|
||||
"guestinfo.vice./storage/scratch_size": "8000000",
|
||||
"guestinfo.vice./init/networks|client/Common/ExecutionEnvironment": "",
|
||||
"init/networks|bridge/network/Common/notes": "",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/Scheme": "ds",
|
||||
"guestinfo.vice..init.sessions|vicadmin.diagnostics.resurrections": "0",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/ForceQuery": "false",
|
||||
"guestinfo.vice./network/container_networks|vmnet/default": "false",
|
||||
"guestinfo.vice..init.sessions|vicadmin.detail.createtime": "0",
|
||||
"guestinfo.vice./storage/VolumeLocations": "default|vol1",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/Path": "[vsanDatastore] volumes/vol1",
|
||||
"guestinfo.vice./init/sessions|vicadmin/cmd/Args": "3",
|
||||
"guestinfo.vice..init.sessions|docker-personality.runblock": "false",
|
||||
"guestinfo.vice./init/version/BuildNumber": "10373",
|
||||
"guestinfo.vice./network/container_networks|vmnet/Common/id": "DistributedVirtualPortgroup:dvportgroup-358",
|
||||
"guestinfo.vice./init/networks|client/network/Common/id": "DistributedVirtualPortgroup:dvportgroup-56",
|
||||
"guestinfo.vice..init.sessions|docker-personality.status": "0",
|
||||
"guestinfo.vice..init.sessions|port-layer.started": "true",
|
||||
"guestinfo.vice./init/sessions|port-layer/runblock": "false",
|
||||
"guestinfo.vice./init/sessions|port-layer/diagnostics/debug": "0",
|
||||
"init/common/name": "test1",
|
||||
"guestinfo.vice..init.sessions|docker-personality.detail.starttime": "0",
|
||||
"guestinfo.vice./storage/VolumeLocations|vol1/RawQuery": "",
|
||||
"init/common/notes": "",
|
||||
"guestinfo.vice./network/container_networks|bridge/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice..init.networks|client.network.assigned.gateway.IP": "CsC//Q==",
|
||||
"guestinfo.vice..init.sessions|vicadmin.detail.starttime": "0",
|
||||
"guestinfo.vice./init/networks|client/Common/name": "client",
|
||||
"guestinfo.vice./init/networks|bridge/static": "true",
|
||||
"network/container_networks|vmnet/Common/notes": "",
|
||||
"guestinfo.vice./init/repo": "",
|
||||
"guestinfo.vice./storage/image_stores": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/runblock": "false",
|
||||
"guestinfo.vice./network/container_networks|vnet/gateway/Mask": "////AA==",
|
||||
"guestinfo.vice..init.networks|client.network.assigned.dns|0": "CqLMAQ==",
|
||||
"guestinfo.vice./init/networks|public/Common/id": "192",
|
||||
"guestinfo.vice./init/networks|public/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/networks|public/network/default": "true",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/Fragment": "",
|
||||
"guestinfo.vice./init/asymrouting": "false",
|
||||
"guestinfo.vice..init.sessions|vicadmin.started": "true",
|
||||
"guestinfo.vice./init/sessions|port-layer/User": "",
|
||||
"guestinfo.vice./init/networks|management/Common/name": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Dir": "",
|
||||
"guestinfo.vice./network/container_networks|vnet/Common/name": "vnet",
|
||||
"guestinfo.vice./network/container_networks|bridge/Common/id": "DistributedVirtualPortgroup:dvportgroup-55",
|
||||
"init/sessions|port-layer/common/notes": "",
|
||||
"guestinfo.vice./network/bridge-ip-range/IP": "rBAAAA==",
|
||||
"guestinfo.vice..init.networks|management.network.assigned.gateway.Mask": "///gAA==",
|
||||
"guestinfo.vice./init/sessions|vicadmin/common/name": "vicadmin",
|
||||
"guestinfo.vice./init/networks|management/network/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/networks|management/static": "false",
|
||||
"guestinfo.vice./init/common/id": "VirtualMachine:vm-365",
|
||||
"guestinfo.vice./network/bridge-ip-range/Mask": "//AAAA==",
|
||||
"guestinfo.vice./vic_machine_create_options": "13",
|
||||
"guestinfo.vice..init.sessions|port-layer.status": "0",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/Opaque": "",
|
||||
"guestinfo.vice./init/networks|client/static": "false",
|
||||
"guestinfo.vice./init/networks|management/network/Common/name": "management",
|
||||
"guestinfo.vice./init/sessions|docker-personality/openstdin": "false",
|
||||
"guestinfo.vice./init/sessions|port-layer/cmd/Args": "2",
|
||||
"guestinfo.vice..init.networks|client.assigned.IP": "CsCoOQ==",
|
||||
"guestinfo.vice./init/networks|public/network/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/version/State": "",
|
||||
"guestinfo.vice./network/container_networks|vmnet/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/attach": "false",
|
||||
"guestinfo.vice./storage/image_stores|0/Opaque": "",
|
||||
"guestinfo.vice..init.networks|client.network.assigned.dns": "1",
|
||||
"guestinfo.vice./init/sessions|port-layer/cmd/Env~": "VC_URL=https://10.192.171.116|DC_PATH=vcqaDC|CS_PATH=/vcqaDC/host/cls|POOL_PATH=|DS_PATH=vsanDatastore",
|
||||
"guestinfo.vice./network/container_networks|bridge/Common/name": "bridge",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/Host": "vsanDatastore",
|
||||
"guestinfo.vice./init/sessions|port-layer/cmd/Env": "4",
|
||||
"guestinfo.vice..init.sessions|port-layer.detail.starttime": "0",
|
||||
"guestinfo.vice./init/networks|management/Common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./init/sessions": "docker-personality|port-layer|vicadmin",
|
||||
"guestinfo.vice..init.sessions|port-layer.detail.createtime": "0",
|
||||
"guestinfo.vice./storage/image_stores|0/Fragment": "",
|
||||
"guestinfo.vice..init.networks|management.assigned.Mask": "///gAA==",
|
||||
"guestinfo.vice./network/container_networks|bridge/default": "false",
|
||||
"guestinfo.vice./container/ContainerNameConvention": "",
|
||||
"guestinfo.vice..init.networks|client.network.type": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/restart": "true",
|
||||
"guestinfo.vice./init/networks|public/network/Common/name": "public",
|
||||
"guestinfo.vice..init.sessions|port-layer.runblock": "false",
|
||||
"guestinfo.vice./init/sessions|port-layer/common/id": "port-layer",
|
||||
"guestinfo.vice./init/networks|client/network/Common/name": "client",
|
||||
"guestinfo.vice./network/container_networks|vnet/pools|0/first": "CgoKAA==",
|
||||
"guestinfo.vice..init.networks|public.network.assigned.gateway.IP": "CsC//Q==",
|
||||
"guestinfo.vice./init/layerid": "",
|
||||
"guestinfo.vice./init/sessions|docker-personality/common/name": "docker-personality",
|
||||
"guestinfo.vice./init/sessions|docker-personality/diagnostics/debug": "0",
|
||||
"guestinfo.vice./container/bootstrap_image_path": "[vsanDatastore] 91512359-242e-5a30-ba4a-0200360a2e79/V1.1.0-RC3-10373-65A1889-bootstrap.iso",
|
||||
"guestinfo.vice..network.container_networks|bridge.type": "bridge",
|
||||
"guestinfo.vice..network.container_networks|vnet.type": "external", "migrate.hostLogState": "none",
|
||||
"init/sessions|vicadmin/common/notes": "",
|
||||
"guestinfo.vice./init/sessions|vicadmin/diagnostics/debug": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/attach": "false",
|
||||
"guestinfo.vice./init/sessions|vicadmin/Group": "vicadmin",
|
||||
"guestinfo.vice./storage/VolumeLocations|default/RawPath": "",
|
||||
"guestinfo.vice./init/networks|bridge/network/default": "false",
|
||||
"guestinfo.vice./init/sessions|port-layer/stopSignal": "",
|
||||
"guestinfo.vice./connect/username": "administrator@vsphere.local",
|
||||
"guestinfo.vice..init.sessions|port-layer.diagnostics.resurrections": "0",
|
||||
"guestinfo.vice./init/common/ExecutionEnvironment": "",
|
||||
"guestinfo.vice./network/bridge_network": "bridge",
|
||||
"guestinfo.vice./registry/whitelist_registries": "1",
|
||||
"guestinfo.vice./registry/whitelist_registries~": "harbor.com:2345|insecure:2345",
|
||||
"guestinfo.vice./registry/insecure_registries~": "insecure:2345",
|
||||
"guestinfo.vice./registry/insecure_registries": "0",
|
||||
"guestinfo.vice./init/sessions|vicadmin/cmd/Env~": "PATH=/sbin:/bin|GOTRACEBACK=all|HTTP_PROXY=http://proxy.vmware.com:2318|HTTPS_PROXY=https://proxy.vmware.com:2318",
|
||||
"guestinfo.vice./init/sessions|docker-personality/cmd/Env~": "PATH=/sbin|GOTRACEBACK=all|HTTP_PROXY=http://proxy.vmware.com:2318|HTTPS_PROXY=https://proxy.vmware.com:2318",
|
||||
}
|
||||
|
||||
commands := map[string][]string{
|
||||
"target": {"https://10.192.171.116"},
|
||||
"thumbprint": {"9F:F0:DF:BA:7F:E2:89:F0:98:E4:A6:D1:58:24:68:74:8A:9B:25:6F"},
|
||||
"image-store": {"vsanDatastore"},
|
||||
"volume-store": {
|
||||
"vsanDatastore/volumes/default:default",
|
||||
"vsanDatastore/volumes/vol1:vol1",
|
||||
},
|
||||
"bridge-network": {"bridge"},
|
||||
"public-network": {"external"},
|
||||
"container-network": {"management:vnet",
|
||||
"vm-network:vmnet",
|
||||
},
|
||||
"container-network-gateway": {"management:10.10.10.1/24"},
|
||||
"container-network-ip-range": {"management:10.10.10.0/24"},
|
||||
|
||||
"debug": {"3"},
|
||||
"insecure-registry": {"insecure:2345"},
|
||||
"whitelist-registry": {"harbor.com:2345", "insecure:2345"},
|
||||
"http-proxy": {"http://proxy.vmware.com:2318"},
|
||||
"https-proxy": {"https://proxy.vmware.com:2318"},
|
||||
}
|
||||
conf := &config.VirtualContainerHostConfigSpec{}
|
||||
extraconfig.DecodeWithPrefix(extraconfig.MapSource(kv), conf, "")
|
||||
|
||||
ctx := context.Background()
|
||||
d, err := validate.NewDataFromConfig(ctx, &testFinder{}, conf)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
dest, err := DataToOption(d)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
}
|
||||
for k, v := range dest {
|
||||
if strings.Contains(k, "store") {
|
||||
for i := range v {
|
||||
v[i] = strings.TrimLeft(v[i], "ds://")
|
||||
}
|
||||
}
|
||||
c := commands[k]
|
||||
testArrays(t, c, v, k)
|
||||
}
|
||||
for k, v := range commands {
|
||||
if strings.Contains(k, "store") {
|
||||
for i := range v {
|
||||
v[i] = strings.TrimLeft(v[i], "ds://")
|
||||
}
|
||||
}
|
||||
c := dest[k]
|
||||
testArrays(t, v, c, k)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testArrays(t *testing.T, l, r []string, key string) {
|
||||
for i := range l {
|
||||
found := false
|
||||
for j := range r {
|
||||
if l[i] == r[j] {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, found, fmt.Sprintf("option value %s mismatch: value %s in array %s is not found in array %s", key, l[i], l, r))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user