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:
130
vendor/github.com/vmware/vic/lib/portlayer/util/paths.go
generated
vendored
Normal file
130
vendor/github.com/vmware/vic/lib/portlayer/util/paths.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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 util
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
)
|
||||
|
||||
const (
|
||||
StorageURLPath = "storage"
|
||||
ImageURLPath = StorageURLPath + "/images"
|
||||
VolumeURLPath = StorageURLPath + "/volumes"
|
||||
)
|
||||
|
||||
// ImageStoreNameToURL parses the image URL in the form /storage/images/<image store>/<image name>
|
||||
func ImageStoreNameToURL(storeName string) (*url.URL, error) {
|
||||
a := ServiceURL(ImageURLPath)
|
||||
AppendDir(a, storeName)
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func ImageStoreName(u *url.URL) (string, error) {
|
||||
// Check the path isn't malformed.
|
||||
if !filepath.IsAbs(u.Path) {
|
||||
return "", errors.New("invalid uri path")
|
||||
}
|
||||
|
||||
segments := strings.Split(filepath.Clean(u.Path), "/")[1:]
|
||||
|
||||
if len(segments) < 3 ||
|
||||
segments[0] != filepath.Clean(StorageURLPath) {
|
||||
return "", errors.New("not a storage path")
|
||||
}
|
||||
|
||||
if segments[1] != "images" {
|
||||
return "", errors.New("not an imagestore path")
|
||||
}
|
||||
|
||||
if len(segments) < 2 {
|
||||
return "", errors.New("uri path mismatch")
|
||||
}
|
||||
|
||||
return segments[2], nil
|
||||
}
|
||||
|
||||
// ImageURL converts a store and image name into an URL that is an internal imagestore representation
|
||||
// NOTE: this is NOT a datastore URL and cannot be used in any calls that expect a ds:// scheme
|
||||
func ImageURL(storeName, imageName string) (*url.URL, error) {
|
||||
if imageName == "" {
|
||||
return nil, fmt.Errorf("image ID missing")
|
||||
}
|
||||
|
||||
u, err := ImageStoreNameToURL(storeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
AppendDir(u, imageName)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// ImageDatastoreURL takes a datastore path object and converts it into a stable URL for with a "ds" scheme
|
||||
func ImageDatastoreURL(path *object.DatastorePath) *url.URL {
|
||||
return &url.URL{
|
||||
Scheme: "ds",
|
||||
Path: path.String(),
|
||||
}
|
||||
}
|
||||
|
||||
// VolumeStoreNameToURL parses the volume URL in the form /storage/volumes/<volume store>/<volume name>
|
||||
func VolumeStoreNameToURL(storeName string) (*url.URL, error) {
|
||||
a := ServiceURL(VolumeURLPath)
|
||||
AppendDir(a, storeName)
|
||||
return a, nil
|
||||
}
|
||||
|
||||
func VolumeStoreName(u *url.URL) (string, error) {
|
||||
// Check the path isn't malformed.
|
||||
if !filepath.IsAbs(u.Path) {
|
||||
return "", errors.New("invalid uri path")
|
||||
}
|
||||
|
||||
segments := strings.Split(filepath.Clean(u.Path), "/")[1:]
|
||||
|
||||
if len(segments) < 3 ||
|
||||
segments[0] != filepath.Clean(StorageURLPath) {
|
||||
return "", errors.New("not a storage path")
|
||||
}
|
||||
|
||||
if segments[1] != "volumes" {
|
||||
return "", errors.New("not an volumestore path")
|
||||
}
|
||||
|
||||
if len(segments) < 2 {
|
||||
return "", errors.New("uri path mismatch")
|
||||
}
|
||||
|
||||
return segments[2], nil
|
||||
}
|
||||
|
||||
func VolumeURL(storeName, volumeName string) (*url.URL, error) {
|
||||
u, err := VolumeStoreNameToURL(storeName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
AppendDir(u, volumeName)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func AppendDir(u *url.URL, dir string) {
|
||||
u.Path = path.Join(u.Path, dir)
|
||||
}
|
||||
124
vendor/github.com/vmware/vic/lib/portlayer/util/paths_test.go
generated
vendored
Normal file
124
vendor/github.com/vmware/vic/lib/portlayer/util/paths_test.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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 util
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestImageStoreName(t *testing.T) {
|
||||
u, _ := url.Parse("/storage/images/imgstore/image")
|
||||
store, err := ImageStoreName(u)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
expectedStore := "imgstore"
|
||||
if !assert.Equal(t, expectedStore, store) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageStoreNameErrors(t *testing.T) {
|
||||
u, _ := url.Parse("fail")
|
||||
_, err := ImageStoreName(u)
|
||||
expectedError := "invalid uri path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
|
||||
u, _ = url.Parse("/storage:123")
|
||||
_, err = ImageStoreName(u)
|
||||
expectedError = "not a storage path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
|
||||
u, _ = url.Parse("/storage")
|
||||
_, err = ImageStoreName(u)
|
||||
expectedError = "not a storage path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageURL(t *testing.T) {
|
||||
DefaultHost, _ = url.Parse("http://foo.com/")
|
||||
storeName := "storeName"
|
||||
imageName := "imageName"
|
||||
|
||||
u, err := ImageURL(storeName, imageName)
|
||||
if err != nil {
|
||||
t.Errorf("ImageURL failed %v", err)
|
||||
}
|
||||
expectedURL := "http://foo.com/storage/images/storeName/imageName"
|
||||
if !assert.Equal(t, expectedURL, u.String()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeStoreName(t *testing.T) {
|
||||
u, _ := url.Parse("/storage/volumes/volstore/volume")
|
||||
store, err := VolumeStoreName(u)
|
||||
if !assert.NoError(t, err) {
|
||||
return
|
||||
}
|
||||
|
||||
expectedStore := "volstore"
|
||||
if !assert.Equal(t, expectedStore, store) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeStoreNameErrors(t *testing.T) {
|
||||
u, _ := url.Parse("fail")
|
||||
_, err := VolumeStoreName(u)
|
||||
expectedError := "invalid uri path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
|
||||
u, _ = url.Parse("/storage:123")
|
||||
_, err = VolumeStoreName(u)
|
||||
expectedError = "not a storage path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
|
||||
u, _ = url.Parse("/storage")
|
||||
_, err = VolumeStoreName(u)
|
||||
expectedError = "not a storage path"
|
||||
if err.Error() != expectedError {
|
||||
t.Errorf("Got: %s Expected: %s", err, expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVolumeURL(t *testing.T) {
|
||||
DefaultHost, _ = url.Parse("http://foo.com/")
|
||||
storeName := "storeName"
|
||||
volumeName := "volumeName"
|
||||
|
||||
u, err := VolumeURL(storeName, volumeName)
|
||||
if err != nil {
|
||||
t.Errorf("VolumeURL failed %v", err)
|
||||
}
|
||||
expectedURL := "http://foo.com/storage/volumes/storeName/volumeName"
|
||||
if !assert.Equal(t, expectedURL, u.String()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
166
vendor/github.com/vmware/vic/lib/portlayer/util/util.go
generated
vendored
Normal file
166
vendor/github.com/vmware/vic/lib/portlayer/util/util.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2016-2018 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/vmware/vic/lib/config"
|
||||
"github.com/vmware/vic/lib/constants"
|
||||
"github.com/vmware/vic/lib/spec"
|
||||
"github.com/vmware/vic/pkg/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
// XXX leaving this as http for now. We probably want to make this unix://
|
||||
scheme = "http://"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultHost = Host()
|
||||
nameTemplateOnce sync.Once
|
||||
nameTemplateInitial string
|
||||
nameTemplate string
|
||||
nameAvailableCapacity int
|
||||
)
|
||||
|
||||
func Host() *url.URL {
|
||||
name, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
thisHost, err := url.Parse(scheme + name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return thisHost
|
||||
}
|
||||
|
||||
// ServiceURL returns the URL for a given service relative to this host
|
||||
func ServiceURL(serviceName string) *url.URL {
|
||||
s, err := DefaultHost.Parse(serviceName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// prepTemplate takes a template string, determines it's suitability for use and adjusts it if necessary
|
||||
// returns:
|
||||
// adjusted template
|
||||
// available length for insertions
|
||||
func prepTemplate(op trace.Operation, template string) (string, int) {
|
||||
if template == "" {
|
||||
template = config.DefaultNamePattern
|
||||
}
|
||||
|
||||
withoutName := strings.Replace(template, config.NameToken.String(), "", 1)
|
||||
withoutEither := strings.Replace(withoutName, config.IDToken.String(), "", 1)
|
||||
availableLen := constants.MaxVMNameLength - len(withoutEither)
|
||||
|
||||
// TODO: initialization time check that template actually contains a token or we have a static string
|
||||
|
||||
// TODO: initialization time check that template is of usable length
|
||||
|
||||
// if there's zero space for replacement then there is no room for parameterization to avoid collisons
|
||||
if availableLen > 0 {
|
||||
return template, availableLen
|
||||
}
|
||||
|
||||
op.Error("Falling back to default name convention as custom convention overflows name capacity")
|
||||
|
||||
template, availableLen = prepTemplate(op, config.DefaultNamePattern)
|
||||
if availableLen > 0 {
|
||||
return template, availableLen
|
||||
}
|
||||
|
||||
// return sane fallback - has bounded length and probably few collisions
|
||||
op.Error("Falling back to raw ID name convention as default convention overflows name capacity")
|
||||
return config.IDToken.String(), constants.MaxVMNameLength
|
||||
}
|
||||
|
||||
// cachedPrepTemplate provides basic single value memoization caching wrapping prepTemplate
|
||||
func cachedPrepTemplate(op trace.Operation, template string) (string, int) {
|
||||
// cache these values for the first template
|
||||
// can move to full memoization if/when we allow dynamic choice or dynamic config
|
||||
nameTemplateOnce.Do(func() {
|
||||
nameTemplateInitial = template
|
||||
nameTemplate, nameAvailableCapacity = prepTemplate(op, template)
|
||||
op.Infof("Cached processed name convention template %q with insertion capacity of %d", nameTemplate, nameAvailableCapacity)
|
||||
})
|
||||
|
||||
if template == nameTemplateInitial {
|
||||
return nameTemplate, nameAvailableCapacity
|
||||
}
|
||||
|
||||
return prepTemplate(op, template)
|
||||
}
|
||||
|
||||
// replaceToken will replace the first occurrence only of the specific PatternToken in the template.
|
||||
// Returns:
|
||||
// updated template with value inserted
|
||||
// renaming available capacity for insertions
|
||||
func replaceToken(template string, token config.PatternToken, value string, availableLen int) (string, int) {
|
||||
if strings.Contains(template, token.String()) {
|
||||
trunc := value
|
||||
if len(value) > availableLen {
|
||||
trunc = value[:availableLen]
|
||||
}
|
||||
|
||||
return strings.Replace(template, token.String(), trunc, 1), availableLen - len(trunc)
|
||||
}
|
||||
|
||||
return template, availableLen
|
||||
}
|
||||
|
||||
// Update the VM display name on vSphere UI
|
||||
func DisplayName(op trace.Operation, cfg *spec.VirtualMachineConfigSpecConfig, namingConvention string) string {
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
prettyName := cfg.Name
|
||||
|
||||
// determine length of template without tokens
|
||||
name, availableLen := cachedPrepTemplate(op, namingConvention)
|
||||
name, availableLen = replaceToken(name, config.IDToken, shortID, availableLen)
|
||||
name, availableLen = replaceToken(name, config.NameToken, prettyName, availableLen)
|
||||
|
||||
op.Infof("Applied naming convention: %s resulting %s", namingConvention, name)
|
||||
return name
|
||||
}
|
||||
|
||||
func ClientIP() (net.IP, error) {
|
||||
ips, err := net.LookupIP(constants.ClientHostName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ips) == 0 {
|
||||
return nil, fmt.Errorf("No IP found on %s", constants.ClientHostName)
|
||||
}
|
||||
|
||||
if len(ips) > 1 {
|
||||
return nil, fmt.Errorf("Multiple IPs found on %s: %#v", constants.ClientHostName, ips)
|
||||
}
|
||||
return ips[0], nil
|
||||
}
|
||||
332
vendor/github.com/vmware/vic/lib/portlayer/util/util_test.go
generated
vendored
Normal file
332
vendor/github.com/vmware/vic/lib/portlayer/util/util_test.go
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
// Copyright 2016-2018 VMware, Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/vmware/vic/lib/config"
|
||||
"github.com/vmware/vic/lib/constants"
|
||||
"github.com/vmware/vic/lib/spec"
|
||||
"github.com/vmware/vic/pkg/trace"
|
||||
)
|
||||
|
||||
// testName allows easy embedding of the test function name in the test body as string data
|
||||
func testName(t *testing.T) string {
|
||||
pc, _, _, ok := runtime.Caller(1)
|
||||
require.True(t, ok, "unable to determine test name")
|
||||
|
||||
// lets only return the func name from the repo (vic)
|
||||
// down - i.e. vic/lib/etc vs. github.com/vmware/vic/lib/etc
|
||||
// if github.com/vmware doesn't match then the original is returned
|
||||
pkgAndFunc := path.Base(runtime.FuncForPC(pc).Name())
|
||||
parts := strings.Split(pkgAndFunc, ".")
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
func TestServiceUrl(t *testing.T) {
|
||||
DefaultHost, _ = url.Parse("http://foo.com/")
|
||||
u := ServiceURL(StorageURLPath)
|
||||
|
||||
if !assert.Equal(t, "http://foo.com/storage", u.String()) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestNameConventionDefault(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s-%s"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String(), config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name, shortID), formatted, "display name not as expected")
|
||||
|
||||
second := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, formatted, second, "second call should return the same output")
|
||||
}
|
||||
|
||||
func TestNameConventionUnspecified(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s-%s"
|
||||
template := ""
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNameInsertOnly(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionIdInsertOnly(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNamePre(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNamePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s-post"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionIDPre(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, shortID), formatted, "display name not as expected")
|
||||
|
||||
}
|
||||
|
||||
func TestNameConventionIDPost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNameBoth(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionIDBoth(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNameAndIDWithPrePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String(), config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, cfg.Name, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionIDAndNameWithPrePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "pre-%s-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String(), config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, fmt.Sprintf(formatString, shortID, cfg.Name), formatted, "display name not as expected")
|
||||
}
|
||||
|
||||
func TestNameConventionNameOverflowWithPrePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "this-is-a-really-long-pre-segment-in-order-to-test-name-truncation-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, constants.MaxVMNameLength, len(formatted), "name was expected to be the max vm name length")
|
||||
}
|
||||
|
||||
func TestNameConventionIDOverflowWithPrePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "this-is-a-really-long-pre-segment-in-order-to-test-name-truncation-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, constants.MaxVMNameLength, len(formatted), "name was expected to be the max vm name length")
|
||||
}
|
||||
|
||||
func TestNameConventionBothOverflowWithPrePost(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "this-is-a-really-long-pre-segment-in-order-to-test-name-truncation-%s-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String(), config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
_ = cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
assert.Equal(t, constants.MaxVMNameLength, len(formatted), "name was expected to be the max vm name length")
|
||||
}
|
||||
|
||||
func TestTemplateOverflow(t *testing.T) {
|
||||
op := trace.NewOperation(context.Background(), testName(t))
|
||||
|
||||
formatString := "this-is-a-really-long-pre-segment-in-order-to-test-name-truncation-that-overflows-without-any-%s-post"
|
||||
template := fmt.Sprintf(formatString, config.IDToken.String(), config.NameToken.String())
|
||||
|
||||
cfg := &spec.VirtualMachineConfigSpecConfig{
|
||||
ID: "abcdefg0123456789hijklmnopqrstu",
|
||||
Name: testName(t),
|
||||
}
|
||||
|
||||
shortID := cfg.ID[:constants.ShortIDLen]
|
||||
|
||||
formatted := DisplayName(op, cfg, template)
|
||||
// behaviour of template overflow is to revert to default template
|
||||
assert.Equal(t, fmt.Sprintf("%s-%s", cfg.Name, shortID), formatted, "display name not as expected")
|
||||
}
|
||||
Reference in New Issue
Block a user