Fix the dependency issue (#231)

This commit is contained in:
Robbie Zhang
2018-06-21 12:09:42 -07:00
committed by GitHub
parent 027b76651d
commit 6ec1098bb8
16629 changed files with 74837 additions and 4975021 deletions

View File

@@ -1,454 +0,0 @@
// Copyright 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 extraconfig
import (
"encoding/base64"
"net"
"net/url"
"os/exec"
"testing"
"time"
"github.com/Sirupsen/logrus"
"github.com/stretchr/testify/assert"
)
// [BEGIN] SLIMMED DOWNED and MODIFIED VERSION of github.com/vmware/vic/lib/metadata
type Common struct {
ExecutionEnvironment string `vic:"0.1" recurse:"depth=0"`
ID string `vic:"0.1" scope:"read-only" key:"id"`
Name string `vic:"0.1" scope:"read-only" key:"name"`
Notes string `vic:"0.1" scope:"read-only" key:"notes"`
}
type ContainerVM struct {
Common `vic:"0.1" scope:"read-only" key:"common"`
Version string `vic:"0.1" scope:"hidden" key:"version"`
Aliases map[string]string `vic:"0.1" recurse:"depth=0"`
Interaction url.URL `vic:"0.1" recurse:"depth=0"`
AgentKey []byte `vic:"0.1" recurse:"depth=0"`
}
type ExecutorConfig struct {
Common `vic:"0.1" scope:"read-only" key:"common"`
Sessions map[string]SessionConfig `vic:"0.1" scope:"hidden" key:"sessions"`
Key string `json:"string"`
}
type ExecutorConfigPointers struct {
Common `vic:"0.1" scope:"read-only" key:"common"`
Sessions map[string]*SessionConfig `vic:"0.1" scope:"hidden" key:"sessions"`
Key string `json:"string"` // will inherit parent vic attributes
}
type Cmd struct {
Path string `vic:"0.1" scope:"hidden" key:"path"`
Args []string `vic:"0.1" scope:"hidden" key:"args"`
Env []string `vic:"0.1" scope:"hidden" key:"env"`
Dir string `vic:"0.1" scope:"hidden" key:"dir"`
Cmd *exec.Cmd `vic:"0.1" scope:"hidden" key:"cmd" recurse:"depth=0"`
}
type SessionConfig struct {
Common `vic:"0.1" scope:"hidden" key:"common" json:"page"`
Cmd Cmd `vic:"0.1" scope:"hidden" key:"cmd"`
Tty bool `vic:"0.1" scope:"hidden" key:"tty"`
}
type ExecutorConfigPointersVisible struct {
Sessions map[string]*VisibleSessionConfig `vic:"0.1" scope:"read-only" key:"sessions"`
}
type VisibleSessionConfig struct {
Cmd Cmd `vic:"0.1" scope:"read-only" key:"cmd"`
Tty bool `vic:"0.1" scope:"read-only" key:"tty"`
}
// [END] SLIMMED VERSION of github.com/vmware/vic/lib/metadata
// make it verbose during testing
func init() {
logger.Level = logrus.DebugLevel
}
func TestBasic(t *testing.T) {
type Type struct {
Int int `vic:"0.1" scope:"read-write" key:"int"`
Bool bool `vic:"0.1" scope:"read-write" key:"bool"`
Float float64 `vic:"0.1" scope:"read-write" key:"float"`
String string `vic:"0.1" scope:"read-write" key:"string"`
}
Struct := Type{
42,
true,
3.14,
"Grrr",
}
encoded := map[string]string{}
Encode(MapSink(encoded), Struct)
expected := map[string]string{
visibleRW("int"): "42",
visibleRW("bool"): "true",
visibleRW("float"): "3.14E+00",
visibleRW("string"): "Grrr",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Struct, decoded, "Encoded and decoded does not match")
}
func TestBasicMap(t *testing.T) {
type Type struct {
IntMap map[string]int `vic:"0.1" scope:"read-only" key:"intmap"`
}
// key is not present
var decoded Type
Decode(MapSource(nil), &decoded)
assert.NotNil(t, decoded.IntMap)
assert.Empty(t, decoded.IntMap)
IntMap := Type{
map[string]int{
"1st": 12345,
"2nd": 67890,
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), IntMap)
expected := map[string]string{
visibleRO("intmap" + Separator + "1st"): "12345",
visibleRO("intmap" + Separator + "2nd"): "67890",
visibleRO("intmap"): "1st" + Separator + "2nd",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
// Decode to new variable
decoded = Type{}
Decode(MapSource(encoded), &decoded)
assert.Equal(t, IntMap, decoded, "Encoded and decoded does not match")
// Decode to already existing variable
IntMapOptimusPrime := Type{
map[string]int{
"first": 1,
"second": 2,
"1st": 0,
},
}
Decode(MapSource(encoded), &IntMapOptimusPrime)
// We expect a merge and over-write
expectedOptimusPrime := Type{
map[string]int{
"1st": 12345,
"2nd": 67890,
"first": 1,
"second": 2,
},
}
assert.Equal(t, IntMapOptimusPrime, expectedOptimusPrime, "Decoded and expected does not match")
}
func TestBasicSlice(t *testing.T) {
type Type struct {
IntSlice []int `vic:"0.1" scope:"read-only" key:"intslice"`
}
IntSlice := Type{
[]int{1, 2, 3, 4, 5},
}
encoded := map[string]string{}
Encode(MapSink(encoded), IntSlice)
expected := map[string]string{
visibleRO("intslice~"): "1" + Separator + "2" + Separator + "3" + Separator + "4" + Separator + "5",
visibleRO("intslice"): "4",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
decoded.IntSlice = make([]int, 1)
Decode(MapSource(encoded), &decoded)
assert.Equal(t, IntSlice, decoded, "Encoded and decoded does not match")
}
func TestStruct(t *testing.T) {
type Type struct {
Common Common `vic:"0.1" scope:"read-only" key:"common"`
}
Struct := Type{
Common: Common{
ID: "0xDEADBEEF",
Name: "Struct",
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), Struct)
expected := map[string]string{
visibleRO("common/id"): "0xDEADBEEF",
visibleRO("common/name"): "Struct",
visibleRO("common/notes"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Struct, decoded, "Encoded and decoded does not match")
}
func TestTime(t *testing.T) {
type Type struct {
Time time.Time `vic:"0.1" scope:"read-only" key:"time"`
}
Time := Type{
Time: time.Date(2009, 11, 10, 23, 00, 00, 0, time.UTC),
}
encoded := map[string]string{}
Encode(MapSink(encoded), Time)
expected := map[string]string{
visibleRO("time"): "2009-11-10 23:00:00 +0000 UTC",
}
assert.Equal(t, encoded, expected, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Time, decoded, "Encoded and decoded does not match")
}
func TestNet(t *testing.T) {
type Type struct {
Net net.IPNet `vic:"0.1" scope:"read-only" key:"net"`
}
// 127.0.0.1/8
n := net.IPNet{IP: net.IP{0x7f, 0x0, 0x0, 0x1}, Mask: net.IPMask{0xff, 0x0, 0x0, 0x0}}
Net := Type{
Net: n,
}
encoded := map[string]string{}
Encode(MapSink(encoded), Net)
expected := map[string]string{
visibleRO("net/IP"): base64.StdEncoding.EncodeToString(n.IP),
visibleRO("net/Mask"): base64.StdEncoding.EncodeToString(n.Mask),
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Net, decoded, "Encoded and decoded does not match")
}
func TestNilNetPointer(t *testing.T) {
type Type struct {
Net *net.IPNet `vic:"0.1" scope:"read-only" key:"net"`
}
Net := Type{
Net: nil,
}
// Net should be nil - pointers are supposed to be nil if the referenced tree is zero valued
encoded := map[string]string{}
Encode(MapSink(encoded), Net)
expected := map[string]string{}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Net, decoded, "Encoded and decoded does not match")
}
func TestPointer(t *testing.T) {
type Type struct {
Pointer *ContainerVM `vic:"0.1" scope:"hidden" key:"pointer"`
PointerOmitnested *ContainerVM `vic:"0.1" scope:"non-persistent" key:"pointeromitnested" recurse:"depth=0"`
}
Pointer := Type{
Pointer: &ContainerVM{Version: "0.1"},
}
encoded := map[string]string{}
Encode(MapSink(encoded), Pointer)
expected := map[string]string{
visibleRO("pointer/common/id"): "",
visibleRO("pointer/common/name"): "",
visibleRO("pointer/common/notes"): "",
"pointer/version": "0.1",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Pointer, decoded, "Encoded and decoded does not match")
}
func TestInheritenceOfNonPersistence(t *testing.T) {
type CommonPersistence struct {
ExecutionEnvironment string `vic:"0.1" recurse:"depth=0"`
ID string `vic:"0.1" scope:"read-only" key:"id"`
Name string `vic:"0.1" scope:"read-only" key:"name"`
Notes string `vic:"0.1" scope:"hidden" key:"notes"`
}
type Type struct {
Common CommonPersistence `vic:"0.1" scope:"read-write,non-persistent" key:"common"`
}
Struct := Type{
Common: CommonPersistence{
ID: "0xDEADBEEF",
Name: "Struct",
},
}
encoded := map[string]string{}
filterSink := ScopeFilterSink(NonPersistent|Hidden, MapSink(encoded))
Encode(filterSink, Struct)
expected := map[string]string{
visibleRONonpersistent("common/id"): "0xDEADBEEF",
visibleRONonpersistent("common/name"): "Struct",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Struct, decoded, "Encoded and decoded does not match")
}
func TestInheritenceOfNonPersistenceWithPointer(t *testing.T) {
type Persistence struct {
ExecutorConfigPointersVisible `vic:"0.1" scope:"read-only,non-persistent" key:"pointers"`
}
Struct := Persistence{
ExecutorConfigPointersVisible: ExecutorConfigPointersVisible{
Sessions: map[string]*VisibleSessionConfig{
"primary": {
Tty: true,
},
},
},
}
encoded := map[string]string{}
filterSink := ScopeFilterSink(NonPersistent|Hidden, MapSink(encoded))
Encode(filterSink, Struct)
expected := map[string]string{
visibleRONonpersistent("pointers/sessions"): "primary",
visibleRONonpersistent("pointers/sessions" + Separator + "primary/tty"): "true",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Persistence
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Struct, decoded, "Encoded and decoded does not match")
}
func TestFilterSink(t *testing.T) {
type CommonPersistence struct {
ExecutionEnvironment string `vic:"0.1" recurse:"depth=0"`
ID string `vic:"0.1" scope:"read-only" key:"id"`
Name string `vic:"0.1" scope:"read-only,non-persistent" key:"name"`
Notes string `vic:"0.1" scope:"read-only" key:"notes"`
}
type Type struct {
Common CommonPersistence `vic:"0.1" scope:"read-write" key:"common"`
}
Struct := Type{
Common: CommonPersistence{
ID: "0xDEADBEEF",
Name: "Struct",
},
}
encoded := map[string]string{}
filterSink := ScopeFilterSink(NonPersistent|Hidden, MapSink(encoded))
Encode(filterSink, Struct)
expected := map[string]string{
visibleRONonpersistent("common/name"): "Struct",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
// strip ID as that would be filtered out
Struct.Common.ID = ""
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Struct, decoded, "Encoded and decoded does not match")
}

View File

@@ -1,537 +0,0 @@
// Copyright 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 extraconfig
import (
"encoding/base64"
"fmt"
"net"
"testing"
"time"
"github.com/Sirupsen/logrus"
"github.com/stretchr/testify/assert"
)
// make it verbose during testing
func init() {
logger.Level = logrus.DebugLevel
}
func TestEmbedded(t *testing.T) {
type Type struct {
Common `vic:"0.1" scope:"read-only" key:"common"`
}
Embedded := Type{
Common: Common{
ID: "0xDEADBEEF",
Name: "Embedded",
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), Embedded)
expected := map[string]string{
visibleRO("common/id"): "0xDEADBEEF",
visibleRO("common/name"): "Embedded",
visibleRO("common/notes"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Embedded, decoded, "Encoded and decoded does not match")
}
func TestNetPointer(t *testing.T) {
type Type struct {
Net *net.IPNet `vic:"0.1" scope:"read-only" key:"net"`
}
// 127.0.0.1/8
n := net.IPNet{IP: net.IP{0x7f, 0x0, 0x0, 0x1}, Mask: net.IPMask{0xff, 0x0, 0x0, 0x0}}
Net := Type{
Net: &n,
}
encoded := map[string]string{}
Encode(MapSink(encoded), Net)
expected := map[string]string{
visibleRO("net/IP"): base64.StdEncoding.EncodeToString(n.IP),
visibleRO("net/Mask"): base64.StdEncoding.EncodeToString(n.Mask),
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Net, decoded, "Encoded and decoded does not match")
}
func TestTimePointer(t *testing.T) {
d := time.Date(2009, 11, 10, 23, 00, 00, 0, time.UTC)
type Type struct {
Time *time.Time `vic:"0.1" scope:"read-only" key:"time"`
}
Time := Type{
Time: &d,
}
encoded := map[string]string{}
Encode(MapSink(encoded), Time)
expected := map[string]string{
visibleRO("time"): "2009-11-10 23:00:00 +0000 UTC",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, Time, decoded, "Encoded and decoded does not match")
}
func TestStructMap(t *testing.T) {
type Type struct {
StructMap map[string]Common `vic:"0.1" scope:"read-only" key:"map"`
}
StructMap := Type{
map[string]Common{
"Key1": {
ID: "0xDEADBEEF",
Name: "beef",
},
"Key2": {
ID: "0x8BADF00D",
Name: "food",
},
"Key3": {
ID: "0xDEADF00D",
Name: "dead",
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), StructMap)
expected := map[string]string{
visibleRO("map" + Separator + "Key1/id"): "0xDEADBEEF",
visibleRO("map" + Separator + "Key1/name"): "beef",
visibleRO("map" + Separator + "Key1/notes"): "",
visibleRO("map" + Separator + "Key2/id"): "0x8BADF00D",
visibleRO("map" + Separator + "Key2/name"): "food",
visibleRO("map" + Separator + "Key2/notes"): "",
visibleRO("map" + Separator + "Key3/id"): "0xDEADF00D",
visibleRO("map" + Separator + "Key3/name"): "dead",
visibleRO("map" + Separator + "Key3/notes"): "",
visibleRO("map"): "Key1" + Separator + "Key2" + Separator + "Key3",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, StructMap, decoded, "Encoded and decoded does not match")
}
func TestIntStructMap(t *testing.T) {
type Type struct {
StructMap map[int]Common `vic:"0.1" scope:"read-only" key:"map"`
}
StructMap := Type{
map[int]Common{
1: {
ID: "0xDEADBEEF",
Name: "beef",
},
2: {
ID: "0x8BADF00D",
Name: "food",
},
3: {
ID: "0xDEADF00D",
Name: "dead",
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), StructMap)
expected := map[string]string{
visibleRO("map" + Separator + "1/id"): "0xDEADBEEF",
visibleRO("map" + Separator + "1/name"): "beef",
visibleRO("map" + Separator + "1/notes"): "",
visibleRO("map" + Separator + "2/id"): "0x8BADF00D",
visibleRO("map" + Separator + "2/name"): "food",
visibleRO("map" + Separator + "2/notes"): "",
visibleRO("map" + Separator + "3/id"): "0xDEADF00D",
visibleRO("map" + Separator + "3/name"): "dead",
visibleRO("map" + Separator + "3/notes"): "",
visibleRO("map"): "1" + Separator + "2" + Separator + "3",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, StructMap, decoded, "Encoded and decoded does not match")
}
func TestStructSlice(t *testing.T) {
type Type struct {
StructSlice []Common `vic:"0.1" scope:"read-only" key:"slice"`
}
StructSlice := Type{
[]Common{
{
ID: "0xDEADFEED",
Name: "feed",
},
{
ID: "0xFACEFEED",
Name: "face",
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), StructSlice)
expected := map[string]string{
visibleRO("slice"): "1",
visibleRO("slice" + Separator + "0/id"): "0xDEADFEED",
visibleRO("slice" + Separator + "0/name"): "feed",
visibleRO("slice" + Separator + "0/notes"): "",
visibleRO("slice" + Separator + "1/id"): "0xFACEFEED",
visibleRO("slice" + Separator + "1/name"): "face",
visibleRO("slice" + Separator + "1/notes"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, StructSlice, decoded, "Encoded and decoded does not match")
}
func TestMultipleScope(t *testing.T) {
MultipleScope := struct {
MultipleScope string `vic:"0.1" scope:"read-only,hidden,non-persistent" key:"multiscope"`
}{
"MultipleScope",
}
encoded := map[string]string{}
Encode(MapSink(encoded), MultipleScope)
expected := map[string]string{}
assert.Equal(t, expected, encoded, "Not equal")
}
func TestUnknownScope(t *testing.T) {
UnknownScope := struct {
UnknownScope int `vic:"0.1" scope:"unknownscope" key:"unknownscope"`
}{
42,
}
encoded := map[string]string{}
Encode(MapSink(encoded), UnknownScope)
expected := map[string]string{}
assert.Equal(t, encoded, expected, "Not equal")
}
func TestUnknownProperty(t *testing.T) {
UnknownProperty := struct {
UnknownProperty int `vic:"0.1" scope:"hidden" key:"unknownproperty" recurse:"unknownproperty"`
}{
42,
}
encoded := map[string]string{}
Encode(MapSink(encoded), UnknownProperty)
expected := map[string]string{
hidden("unknownproperty"): "42",
}
assert.Equal(t, expected, encoded, "Not equal")
}
func TestOmitNested(t *testing.T) {
OmitNested := struct {
Time time.Time `vic:"0.1" scope:"volatile" key:"time" recurse:"depth=0"`
CurrentTime time.Time `vic:"0.1" scope:"volatile" key:"time"`
}{
Time: time.Date(2009, 11, 10, 23, 00, 00, 0, time.UTC),
CurrentTime: time.Date(2009, 11, 10, 23, 00, 00, 0, time.UTC),
}
encoded := map[string]string{}
Encode(MapSink(encoded), OmitNested)
expected := map[string]string{
visibleRO("time"): "2009-11-10 23:00:00 +0000 UTC",
}
assert.Equal(t, expected, encoded, "Encoded and decoded does not match")
}
func TestComplex(t *testing.T) {
type Type struct {
ExecutorConfig ExecutorConfig `vic:"0.1" scope:"hidden" key:"executorconfig"`
}
ExecutorConfig := Type{
ExecutorConfig{
Sessions: map[string]SessionConfig{
"Session1": {
Common: Common{
ID: "SessionID",
Name: "SessionName",
},
Tty: true,
Cmd: Cmd{
Path: "/vmware",
Args: []string{"/bin/imagec", "-standalone"},
Env: []string{"PATH=/bin", "USER=imagec"},
Dir: "/",
},
},
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), ExecutorConfig)
expected := map[string]string{
visibleRO("executorconfig/common/id"): "",
visibleRO("executorconfig/common/name"): "",
visibleRO("executorconfig/common/notes"): "",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/id"): "SessionID",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/name"): "SessionName",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/notes"): "",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/path"): "/vmware",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/args~"): "/bin/imagec" + Separator + "-standalone",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/args"): "1",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/env~"): "PATH=/bin" + Separator + "USER=imagec",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/env"): "1",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/dir"): "/",
hidden("executorconfig/sessions" + Separator + "Session1/tty"): "true",
hidden("executorconfig/sessions"): "Session1",
hidden("executorconfig/Key"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, ExecutorConfig, decoded, "Encoded and decoded does not match")
}
func TestComplexPointer(t *testing.T) {
type Type struct {
ExecutorConfig *ExecutorConfig `vic:"0.1" scope:"hidden" key:"executorconfig"`
}
ExecutorConfig := Type{
&ExecutorConfig{
Sessions: map[string]SessionConfig{
"Session1": {
Common: Common{
ID: "SessionID",
Name: "SessionName",
},
Tty: true,
Cmd: Cmd{
Path: "/vmware",
Args: []string{"/bin/imagec", "-standalone"},
Env: []string{"PATH=/bin", "USER=imagec"},
Dir: "/",
},
},
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), ExecutorConfig)
expected := map[string]string{
visibleRO("executorconfig/common/id"): "",
visibleRO("executorconfig/common/name"): "",
visibleRO("executorconfig/common/notes"): "",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/id"): "SessionID",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/name"): "SessionName",
visibleRO("executorconfig/sessions" + Separator + "Session1/common/notes"): "",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/path"): "/vmware",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/args~"): "/bin/imagec" + Separator + "-standalone",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/args"): "1",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/env~"): "PATH=/bin" + Separator + "USER=imagec",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/env"): "1",
hidden("executorconfig/sessions" + Separator + "Session1/cmd/dir"): "/",
hidden("executorconfig/sessions" + Separator + "Session1/tty"): "true",
hidden("executorconfig/sessions"): "Session1",
hidden("executorconfig/Key"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Type
Decode(MapSource(encoded), &decoded)
assert.Equal(t, ExecutorConfig, decoded, "Encoded and decoded does not match")
}
// TestPointerDecode tests the translation from a type where the sessions are direct values to
// one where they are pointers
func TestPointerDecode(t *testing.T) {
reference := ExecutorConfig{
Sessions: map[string]SessionConfig{
"Session1": {
Common: Common{
ID: "SessionID",
Name: "SessionName",
},
Tty: true,
Cmd: Cmd{
Path: "/vmware",
Args: []string{"/bin/imagec", "-standalone"},
Env: []string{"PATH=/bin", "USER=imagec"},
Dir: "/",
},
},
},
}
encoded := map[string]string{}
Encode(MapSink(encoded), reference)
expected := map[string]string{
visibleRO("common/id"): "",
visibleRO("common/name"): "",
visibleRO("common/notes"): "",
visibleRO("sessions" + Separator + "Session1/common/id"): "SessionID",
visibleRO("sessions" + Separator + "Session1/common/name"): "SessionName",
visibleRO("sessions" + Separator + "Session1/common/notes"): "",
hidden("sessions" + Separator + "Session1/cmd/path"): "/vmware",
hidden("sessions" + Separator + "Session1/cmd/args~"): "/bin/imagec" + Separator + "-standalone",
hidden("sessions" + Separator + "Session1/cmd/args"): "1",
hidden("sessions" + Separator + "Session1/cmd/env~"): "PATH=/bin" + Separator + "USER=imagec",
hidden("sessions" + Separator + "Session1/cmd/env"): "1",
hidden("sessions" + Separator + "Session1/cmd/dir"): "/",
hidden("sessions" + Separator + "Session1/tty"): "true",
hidden("sessions"): "Session1",
hidden("Key"): "",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded ExecutorConfigPointers
Decode(MapSource(encoded), &decoded)
// cannot assert equality at a high level because of the different structure types, but we can test the
// common structure fragments
assert.Equal(t, reference.Sessions["Session1"], *decoded.Sessions["Session1"], "Encoded and decoded sessions do not match")
}
func TestInsideOutside(t *testing.T) {
type Inside struct {
ID string `vic:"0.1" scope:"read-write" key:"id"`
Name string `vic:"0.1" scope:"read-write" key:"name"`
}
type Outside struct {
Inside Inside `vic:"0.1" scope:"read-only" key:"inside"`
ID string `vic:"0.1" scope:"read-write" key:"id"`
Name string `vic:"0.1" scope:"read-write" key:"name"`
}
outside := Outside{
Inside: Inside{
ID: "inside",
Name: "Inside",
},
ID: "outside",
Name: "Outside",
}
encoded := map[string]string{}
Encode(MapSink(encoded), outside)
expected := map[string]string{
visibleRW("inside.id"): "inside",
visibleRW("inside.name"): "Inside",
visibleRW("id"): "outside",
visibleRW("name"): "Outside",
}
assert.Equal(t, expected, encoded, "Encoded and expected does not match")
var decoded Outside
Decode(MapSource(encoded), &decoded)
assert.Equal(t, outside, decoded, "Encoded and decoded does not match")
}
func TestIPSlice(t *testing.T) {
type Slice struct {
Slice []net.IP `vic:"0.1" scope:"read-only" key:"slice"`
}
ips := []net.IP{
net.ParseIP("10.10.10.10"),
net.ParseIP("10.10.10.1"),
}
encodedIPs := make([]string, len(ips))
for i := range ips {
Encode(func(key, value string) error {
encodedIPs[i] = value
return nil
}, ips[i])
}
s := Slice{
Slice: ips,
}
encoded := make(map[string]string)
Encode(MapSink(encoded), s)
expected := map[string]string{
visibleRO("slice"): fmt.Sprintf("%d", len(ips)-1),
}
for i := range encodedIPs {
expected[visibleRO(fmt.Sprintf("slice"+Separator+"%d", i))] = encodedIPs[i]
}
assert.Equal(t, expected, encoded, "Encoded and expected do not match")
var decoded Slice
Decode(MapSource(encoded), &decoded)
assert.Equal(t, s, decoded, "Encoded and decoded do not match")
}

View File

@@ -1,21 +0,0 @@
// Copyright 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 extraconfig
import "testing"
func TestExistingBasic(t *testing.T) {
t.Skip("decode into existing target tests not yet implemented")
}

View File

@@ -1,269 +0,0 @@
// Copyright 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 extraconfig
import (
"testing"
"strings"
"github.com/stretchr/testify/assert"
)
func visibleRO(key string) string {
return calculateKey(calculateScope([]string{"read-only"}), "", key)
}
func visibleRONonpersistent(key string) string {
return calculateKey(calculateScope([]string{"read-only", "non-persistent"}), "", key)
}
func visibleRW(key string) string {
return calculateKey(calculateScope([]string{"read-write"}), "", key)
}
func hidden(key string) string {
return calculateKey(calculateScope([]string{"hidden"}), "", key)
}
func TestHidden(t *testing.T) {
scopes := []string{"hidden"}
key := calculateKey(calculateScope(scopes), "a/b", "c")
assert.Equal(t, "a/b/c", key, "Key should remain hidden")
}
func TestHide(t *testing.T) {
scopes := []string{"hidden"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+"/a/b", "c")
assert.Equal(t, "a/b/c", key, "Key should be hidden")
}
func TestReveal(t *testing.T) {
scopes := []string{"read-only"}
key := calculateKey(calculateScope(scopes), "a/b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+"/a/b/c", key, "Key should be exposed")
}
func TestVisibleReadOnly(t *testing.T) {
scopes := []string{"read-only"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+"/a/b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+"/a/b/c", key, "Key should be remain visible and read-only")
}
func TestVisibleReadWrite(t *testing.T) {
scopes := []string{"read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+".a.b.c", key, "Key should be remain visible and read-write")
}
func TestTopLevelReadOnly(t *testing.T) {
scopes := []string{"read-only"}
key := calculateKey(calculateScope(scopes), "", "a")
assert.Equal(t, DefaultGuestInfoPrefix+"/a", key, "Key should be visible and read-only")
}
func TestReadOnlyToReadWrite(t *testing.T) {
scopes := []string{"read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+"/a/b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+".a.b.c", key, "Key should be visible and change to read-write")
}
func TestReadWriteToReadOnly(t *testing.T) {
scopes := []string{"read-only"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+"/a/b/c", key, "Key should be visible and change to read-only")
}
func TestCompoundKey(t *testing.T) {
scopes := []string{"read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a", "b/c")
assert.Equal(t, DefaultGuestInfoPrefix+".a.b.c", key, "Key should be visible and read-write")
}
func TestNoScopes(t *testing.T) {
scopes := []string{}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a/b", "c")
assert.Equal(t, "a/b/c", key, "Key should be completely proscriptive")
key = calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.Equal(t, "a.b/c", key, "Key should be hidden")
key = calculateKey(calculateScope(scopes), "a.b", "c")
assert.Equal(t, "a.b/c", key, "Key should remain hidden")
}
func TestSecret(t *testing.T) {
scopes := []string{"secret", "read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+".a.b.c"+suffixSeparator+secretSuffix, key, "Key should have secret suffix")
}
func TestNonpersistent(t *testing.T) {
scopes := []string{"non-persistent", "read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.Equal(t, DefaultGuestInfoPrefix+".a.b.c"+suffixSeparator+nonpersistentSuffix, key, "Key should have non-persistent suffix")
}
func TestMultipleSuffixes(t *testing.T) {
scopes := []string{"non-persistent", "secret", "read-write"}
key := calculateKey(calculateScope(scopes), DefaultGuestInfoPrefix+".a.b", "c")
assert.True(t, strings.Contains(key, suffixSeparator+secretSuffix) && strings.Contains(key, suffixSeparator+nonpersistentSuffix), "Key should contain both secret and non-persistent suffix")
}
func TestCalculateKeys(t *testing.T) {
type AStruct struct {
I int
}
type Type struct {
ExecutorConfig ExecutorConfig `vic:"0.1" scope:"hidden" key:"executorconfig"`
Array []AStruct `vic:"0.1" scope:"read-write" key:"array"`
Ptr *AStruct `vic:"0.1" scope:"read-only" key:"ptr"`
Str string `vic:"0.1" scope:"read-only" key:"str"`
Bytes []uint8 `vic:"0.1" scope:"read-write" key:"bytes"`
}
ec := Type{
ExecutorConfig: ExecutorConfig{
Sessions: map[string]SessionConfig{
"Session1": {
Common: Common{
ID: "SessionID",
Name: "SessionName",
},
Tty: true,
Cmd: Cmd{
Path: "/vmware",
Args: []string{"/bin/imagec", "-standalone"},
Env: []string{"PATH=/bin", "USER=imagec"},
Dir: "/",
},
},
},
},
Array: []AStruct{
{I: 0},
},
Ptr: &AStruct{
I: 1,
},
Str: "foo",
Bytes: []byte{0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf},
}
var tests = []struct {
in string
out []string
}{
{
"ExecutorConfig.*",
[]string{
visibleRO("executorconfig/common"),
hidden("executorconfig/sessions"),
"executorconfig/Key",
},
},
{
"ExecutorConfig.Sessions.*",
[]string{"executorconfig/sessions" + Separator + "Session1"},
},
{
"ExecutorConfig.Sessions.Session1.Cmd.Args",
[]string{"executorconfig/sessions" + Separator + "Session1/cmd/args"},
},
{
"ExecutorConfig.Sessions.*.Cmd.Args.*",
[]string{"executorconfig/sessions" + Separator + "Session1/cmd/args~"},
},
{
"ExecutorConfig.Sessions.*.Cmd.Args.0",
[]string{"executorconfig/sessions" + Separator + "Session1/cmd/args~"},
},
{
"Array.0.I",
[]string{visibleRW("array" + Separator + "0/I")},
},
{
"Array.*",
[]string{visibleRW("array" + Separator + "0")},
},
{
"Ptr.I",
[]string{visibleRO("ptr/I")},
},
{
"Str",
[]string{visibleRO("str")},
},
{
"Bytes",
[]string{visibleRW("bytes")},
},
{
"Bytes.0",
[]string{visibleRW("bytes")},
},
{
"Bytes.*",
[]string{visibleRW("bytes")},
},
}
for _, te := range tests {
keys := CalculateKeys(ec, te.in, "")
assert.Equal(t, te.out, keys)
}
panicTests := []string{
"Array.1.I",
"Array.0.i",
"Array.f.i",
"ExecutorConfig.foo",
"foo",
"ExecutorConfig.Sessions.foo",
"Str.*",
"Str.foo",
}
for _, te := range panicTests {
assert.Panics(t, func() {
CalculateKeys(ec, te, "")
})
}
}

View File

@@ -1,67 +0,0 @@
// Copyright 2016-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 extraconfig
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSecretFields(t *testing.T) {
type tell struct {
Who string `vic:"0.1" scope:"secret" key:"who"`
}
type stuff struct {
Username string `vic:"0.1" scope:"read-only" key:"username"`
Password string `vic:"0.1" scope:"secret" key:"password"`
Tell tell
}
config := stuff{
Username: "root",
Password: "super-s@fe-passw0rd",
Tell: tell{"noone"},
}
out, err := NewSecretKey()
if err != nil {
t.Fatal(err)
}
encoded := map[string]string{}
Encode(out.Sink(MapSink(encoded)), config)
password := encoded["guestinfo.vice./password"+suffixSeparator+secretSuffix]
assert.NotEmpty(t, password, "encrypted password")
assert.NotEqual(t, password, config.Password, "encrypted password")
for _, expectEq := range []bool{true, false} {
var in SecretKey
var decoded stuff
Decode(in.Source(MapSource(encoded)), &decoded)
if expectEq {
assert.Equal(t, config, decoded, "Encoded and decoded does not match")
} else {
assert.NotEqual(t, config, decoded, "Encoded and decoded should not not match")
}
// second time should fail to decrypt w/o GuestInfoSecretKey
delete(encoded, GuestInfoSecretKey)
}
}

View File

@@ -1,55 +0,0 @@
// Copyright 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 vmomi
import (
"testing"
"reflect"
"github.com/stretchr/testify/assert"
"github.com/vmware/govmomi/vim25/types"
)
func TestDelta(t *testing.T) {
new := map[string]string{
"hello": "goodbye",
"cruel": "world",
"is": "not",
"enough": "already",
}
existing := []types.BaseOptionValue{
&types.OptionValue{Key: "hello", Value: "goodbye"},
&types.OptionValue{Key: "is", Value: "always"},
&types.OptionValue{Key: "present", Value: "regardless"},
}
updatesSlice := OptionValueUpdatesFromMap(existing, new)
expected := map[string]string{
"enough": "already", // added
"cruel": "world", // added
"is": "not", // changed
}
// turn them back into maps for equality check
updates := OptionValueMap(updatesSlice)
if !assert.True(t, reflect.DeepEqual(expected, updates), "DeepEqual says they do not match") {
t.Fatalf("Expected: %+q \nActual: %+q\n", expected, updates)
}
}

View File

@@ -1,140 +0,0 @@
// Copyright 2016-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 vmomi is in a separate package to avoid the transitive inclusion of govmomi
// as a fundamental dependency of the main extraconfig
package vmomi
import (
"fmt"
"github.com/vmware/govmomi/vim25/types"
"github.com/vmware/vic/pkg/vsphere/extraconfig"
)
// OptionValueMap returns a map from array of OptionValues
func OptionValueMap(src []types.BaseOptionValue) map[string]string {
// create the key/value store from the extraconfig slice for lookups
kv := make(map[string]string)
for i := range src {
k := src[i].GetOptionValue().Key
v := src[i].GetOptionValue().Value.(string)
kv[k] = unescapeNil(v)
}
return kv
}
// OptionValueSource is a convenience method to generate a MapSource source from
// and array of OptionValue's
func OptionValueSource(src []types.BaseOptionValue) extraconfig.DataSource {
kv := OptionValueMap(src)
return extraconfig.MapSource(kv)
}
// OptionValueFromMap is a convenience method to convert a map into a BaseOptionValue array
// escapeNil - if true a nil string is replaced with "<nil>". Allows us to distinguish between
// deletion and nil as a value
func OptionValueFromMap(data map[string]string, escape bool) []types.BaseOptionValue {
if len(data) == 0 {
return nil
}
array := make([]types.BaseOptionValue, len(data))
i := 0
for k, v := range data {
if escape {
v = escapeNil(v)
}
array[i] = &types.OptionValue{Key: k, Value: v}
i++
}
return array
}
// OptionValueArrayToString translates the options array in to a Go formatted structure dump
func OptionValueArrayToString(options []types.BaseOptionValue) string {
// create the key/value store from the extraconfig slice for lookups
kv := make(map[string]string)
for i := range options {
k := options[i].GetOptionValue().Key
v := options[i].GetOptionValue().Value.(string)
kv[k] = v
}
return fmt.Sprintf("%#v", kv)
}
// OptionValueUpdatesFromMap generates an optionValue array for those entries in the map that do not
// already exist, are changed from the reference array, or a removed
// A removed entry will have a nil string for the value
// NOTE: DOES NOT CURRENTLY SUPPORT DELETION OF KEYS - KEYS MISSING FROM NEW MAP ARE IGNORED
func OptionValueUpdatesFromMap(existing []types.BaseOptionValue, new map[string]string) []types.BaseOptionValue {
e := len(existing)
if e == 0 {
return OptionValueFromMap(new, true)
}
n := len(new)
updates := make(map[string]string, n+e)
unchanged := make(map[string]struct{}, n+e)
// first the existing keys
for i := range existing {
v := existing[i].GetOptionValue()
if nV, ok := new[v.Key]; ok && nV == v.Value.(string) {
unchanged[v.Key] = struct{}{}
// no change
continue
} else if ok {
// changed
updates[v.Key] = escapeNil(nV)
} else {
// deletion
// NOTE: ignored as this also deletes non VIC entries currently
// there's no prefix for the non-guestinfo keys so cannot easily filter
// updates[v.Key] = ""
}
}
// now the new keys
for k, v := range new {
if _, ok := unchanged[k]; ok {
continue
}
if _, ok := updates[k]; !ok {
updates[k] = escapeNil(v)
}
}
return OptionValueFromMap(updates, false)
}
func escapeNil(input string) string {
if input == "" {
return "<nil>"
}
return input
}
func unescapeNil(input string) string {
if input == "<nil>" {
return ""
}
return input
}