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:
Loc Nguyen
2018-06-04 15:41:32 -07:00
committed by Ria Bhatia
parent 98a111e8b7
commit 513cebe7b7
6296 changed files with 1123685 additions and 8 deletions

298
vendor/github.com/go-openapi/loads/fmts/fixture_test.go generated vendored Normal file
View File

@@ -0,0 +1,298 @@
// Copyright 2015 go-swagger maintainers
//
// 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 fmts
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"strings"
"testing"
"github.com/go-openapi/spec"
"github.com/stretchr/testify/assert"
)
var extensions = []string{"json"}
func assertSpecJSON(t testing.TB, specJSON []byte) bool {
var expected map[string]interface{}
if !assert.NoError(t, json.Unmarshal(specJSON, &expected)) {
return false
}
obj := spec.Swagger{}
if !assert.NoError(t, json.Unmarshal(specJSON, &obj)) {
return false
}
cb, err := json.MarshalIndent(obj, "", " ")
if assert.NoError(t, err) {
return false
}
var actual map[string]interface{}
if !assert.NoError(t, json.Unmarshal(cb, &actual)) {
return false
}
return assertSpecMaps(t, actual, expected)
}
func assertSpecMaps(t testing.TB, actual, expected map[string]interface{}) bool {
res := true
if id, ok := expected["id"]; ok {
res = assert.Equal(t, id, actual["id"])
}
res = res && assert.Equal(t, expected["consumes"], actual["consumes"])
res = res && assert.Equal(t, expected["produces"], actual["produces"])
res = res && assert.Equal(t, expected["schemes"], actual["schemes"])
res = res && assert.Equal(t, expected["swagger"], actual["swagger"])
res = res && assert.Equal(t, expected["info"], actual["info"])
res = res && assert.Equal(t, expected["host"], actual["host"])
res = res && assert.Equal(t, expected["basePath"], actual["basePath"])
res = res && assert.Equal(t, expected["paths"], actual["paths"])
res = res && assert.Equal(t, expected["definitions"], actual["definitions"])
res = res && assert.Equal(t, expected["responses"], actual["responses"])
res = res && assert.Equal(t, expected["securityDefinitions"], actual["securityDefinitions"])
res = res && assert.Equal(t, expected["tags"], actual["tags"])
res = res && assert.Equal(t, expected["externalDocs"], actual["externalDocs"])
res = res && assert.Equal(t, expected["x-some-extension"], actual["x-some-extension"])
res = res && assert.Equal(t, expected["x-schemes"], actual["x-schemes"])
return res
}
func roundTripTest(t *testing.T, fixtureType, extension, fileName string, schema interface{}) bool {
if extension == "yaml" {
return roundTripTestYAML(t, fixtureType, fileName, schema)
}
return roundTripTestJSON(t, fixtureType, fileName, schema)
}
func roundTripTestJSON(t *testing.T, fixtureType, fileName string, schema interface{}) bool {
specName := strings.TrimSuffix(fileName, filepath.Ext(fileName))
t.Logf("verifying %s JSON fixture %q", fixtureType, specName)
b, err := ioutil.ReadFile(fileName)
if !assert.NoError(t, err) {
return false
}
var expected map[string]interface{}
if !assert.NoError(t, json.Unmarshal(b, &expected)) {
return false
}
if !assert.NoError(t, json.Unmarshal(b, schema)) {
return false
}
cb, err := json.MarshalIndent(schema, "", " ")
if !assert.NoError(t, err) {
return false
}
var actual map[string]interface{}
if !assert.NoError(t, json.Unmarshal(cb, &actual)) {
return false
}
return assert.EqualValues(t, expected, actual)
}
func roundTripTestYAML(t *testing.T, fixtureType, fileName string, schema interface{}) bool {
specName := strings.TrimSuffix(fileName, filepath.Ext(fileName))
t.Logf("verifying %s YAML fixture %q", fixtureType, specName)
b, err := YAMLDoc(fileName)
if !assert.NoError(t, err) {
return false
}
var expected map[string]interface{}
if !assert.NoError(t, json.Unmarshal(b, &expected)) {
return false
}
if !assert.NoError(t, json.Unmarshal(b, schema)) {
return false
}
cb, err := json.MarshalIndent(schema, "", " ")
if !assert.NoError(t, err) {
return false
}
var actual map[string]interface{}
if !assert.NoError(t, json.Unmarshal(cb, &actual)) {
return false
}
return assert.EqualValues(t, expected, actual)
}
func TestPropertyFixtures(t *testing.T) {
for _, extension := range extensions {
path := filepath.Join("..", "fixtures", extension, "models", "properties")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
// for _, f := range files {
// roundTripTest(t, "property", extension, filepath.Join(path, f.Name()), &Schema{})
// }
f := files[0]
roundTripTest(t, "property", extension, filepath.Join(path, f.Name()), &spec.Schema{})
}
}
func TestAdditionalPropertiesWithObject(t *testing.T) {
schema := new(spec.Schema)
b, err := YAMLDoc("../fixtures/yaml/models/modelWithObjectMap.yaml")
if assert.NoError(t, err) {
var expected map[string]interface{}
if assert.NoError(t, json.Unmarshal(b, &expected)) && assert.NoError(t, json.Unmarshal(b, schema)) {
cb, err := json.MarshalIndent(schema, "", " ")
if assert.NoError(t, err) {
var actual map[string]interface{}
if assert.NoError(t, json.Unmarshal(cb, &actual)) {
assert.Equal(t, expected, actual)
}
}
}
}
}
func TestModelFixtures(t *testing.T) {
path := filepath.Join("..", "fixtures", "json", "models")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
specs := []string{"modelWithObjectMap", "models", "modelWithComposition", "modelWithExamples", "multipleModels"}
FILES:
for _, f := range files {
if f.IsDir() {
continue
}
for _, sp := range specs {
if strings.HasPrefix(f.Name(), sp) {
roundTripTest(t, "model", "json", filepath.Join(path, f.Name()), &spec.Schema{})
continue FILES
}
}
//fmt.Println("trying", f.Name())
roundTripTest(t, "model", "json", filepath.Join(path, f.Name()), &spec.Schema{})
}
path = filepath.Join("..", "fixtures", "yaml", "models")
files, err = ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
YAMLFILES:
for _, f := range files {
if f.IsDir() {
continue
}
for _, sp := range specs {
if strings.HasPrefix(f.Name(), sp) {
roundTripTest(t, "model", "yaml", filepath.Join(path, f.Name()), &spec.Schema{})
continue YAMLFILES
}
}
// fmt.Println("trying", f.Name())
roundTripTest(t, "model", "yaml", filepath.Join(path, f.Name()), &spec.Schema{})
}
}
func TestParameterFixtures(t *testing.T) {
path := filepath.Join("..", "fixtures", "json", "resources", "parameters")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
for _, f := range files {
roundTripTest(t, "parameter", "json", filepath.Join(path, f.Name()), &spec.Parameter{})
}
}
func TestOperationFixtures(t *testing.T) {
path := filepath.Join("..", "fixtures", "json", "resources", "operations")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
for _, f := range files {
roundTripTest(t, "operation", "json", filepath.Join(path, f.Name()), &spec.Operation{})
}
}
func TestResponseFixtures(t *testing.T) {
path := filepath.Join("..", "fixtures", "json", "responses")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
for _, f := range files {
if !strings.HasPrefix(f.Name(), "multiple") {
roundTripTest(t, "response", "json", filepath.Join(path, f.Name()), &spec.Response{})
} else {
roundTripTest(t, "responses", "json", filepath.Join(path, f.Name()), &spec.Responses{})
}
}
}
func TestResourcesFixtures(t *testing.T) {
path := filepath.Join("..", "fixtures", "json", "resources")
files, err := ioutil.ReadDir(path)
if err != nil {
t.Fatal(err)
}
pathItems := []string{"resourceWithLinkedDefinitions_part1"}
toSkip := []string{}
FILES:
for _, f := range files {
if f.IsDir() {
continue
}
for _, ts := range toSkip {
if strings.HasPrefix(f.Name(), ts) {
t.Log("verifying resource" + strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())))
b, err := ioutil.ReadFile(filepath.Join(path, f.Name()))
if assert.NoError(t, err) {
assertSpecJSON(t, b)
}
continue FILES
}
}
for _, pi := range pathItems {
if strings.HasPrefix(f.Name(), pi) {
roundTripTest(t, "path items", "json", filepath.Join(path, f.Name()), &spec.PathItem{})
continue FILES
}
}
t.Logf("verifying resource %q", strings.TrimSuffix(f.Name(), filepath.Ext(f.Name())))
b2, err := ioutil.ReadFile(filepath.Join(path, f.Name()))
if assert.NoError(t, err) {
assertSpecJSON(t, b2)
}
}
}

112
vendor/github.com/go-openapi/loads/fmts/yaml.go generated vendored Normal file
View File

@@ -0,0 +1,112 @@
// Copyright 2015 go-swagger maintainers
//
// 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 fmts
import (
"encoding/json"
"fmt"
"path/filepath"
"strconv"
"github.com/go-openapi/swag"
"gopkg.in/yaml.v2"
)
// YAMLMatcher matches yaml
func YAMLMatcher(path string) bool {
ext := filepath.Ext(path)
return ext == ".yaml" || ext == ".yml"
}
// YAMLToJSON converts YAML unmarshaled data into json compatible data
func YAMLToJSON(data interface{}) (json.RawMessage, error) {
jm, err := transformData(data)
if err != nil {
return nil, err
}
b, err := swag.WriteJSON(jm)
return json.RawMessage(b), err
}
func BytesToYAMLDoc(data []byte) (interface{}, error) {
var document map[interface{}]interface{}
if err := yaml.Unmarshal(data, &document); err != nil {
return nil, err
}
return document, nil
}
func transformData(in interface{}) (out interface{}, err error) {
switch in.(type) {
case map[interface{}]interface{}:
o := make(map[string]interface{})
for k, v := range in.(map[interface{}]interface{}) {
sk := ""
switch k.(type) {
case string:
sk = k.(string)
case int:
sk = strconv.Itoa(k.(int))
default:
return nil, fmt.Errorf("types don't match: expect map key string or int get: %T", k)
}
v, err = transformData(v)
if err != nil {
return nil, err
}
o[sk] = v
}
return o, nil
case []interface{}:
in1 := in.([]interface{})
len1 := len(in1)
o := make([]interface{}, len1)
for i := 0; i < len1; i++ {
o[i], err = transformData(in1[i])
if err != nil {
return nil, err
}
}
return o, nil
}
return in, nil
}
// YAMLDoc loads a yaml document from either http or a file and converts it to json
func YAMLDoc(path string) (json.RawMessage, error) {
yamlDoc, err := YAMLData(path)
if err != nil {
return nil, err
}
data, err := YAMLToJSON(yamlDoc)
if err != nil {
return nil, err
}
return json.RawMessage(data), nil
}
// YAMLData loads a yaml document from either http or a file
func YAMLData(path string) (interface{}, error) {
data, err := swag.LoadFromFileOrHTTP(path)
if err != nil {
return nil, err
}
return BytesToYAMLDoc(data)
}

442
vendor/github.com/go-openapi/loads/fmts/yaml_test.go generated vendored Normal file
View File

@@ -0,0 +1,442 @@
// Copyright 2015 go-swagger maintainers
//
// 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 fmts
import (
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-openapi/swag"
"github.com/stretchr/testify/assert"
)
type failJSONMarhal struct {
}
func (f failJSONMarhal) MarshalJSON() ([]byte, error) {
return nil, errors.New("expected")
}
func TestLoadHTTPBytes(t *testing.T) {
_, err := swag.LoadFromFileOrHTTP("httx://12394:abd")
assert.Error(t, err)
serv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusNotFound)
}))
defer serv.Close()
_, err = swag.LoadFromFileOrHTTP(serv.URL)
assert.Error(t, err)
ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte("the content"))
}))
defer ts2.Close()
d, err := swag.LoadFromFileOrHTTP(ts2.URL)
assert.NoError(t, err)
assert.Equal(t, []byte("the content"), d)
}
func TestYAMLToJSON(t *testing.T) {
data := make(map[interface{}]interface{})
data[1] = "the int key value"
data["name"] = "a string value"
data["y"] = "some value"
d, err := YAMLToJSON(data)
if assert.NoError(t, err) {
assert.Equal(t, `{"1":"the int key value","name":"a string value","y":"some value"}`, string(d))
}
data[true] = "the bool value"
d, err = YAMLToJSON(data)
assert.Error(t, err)
assert.Nil(t, d)
delete(data, true)
tag := make(map[interface{}]interface{})
tag["name"] = "tag name"
data["tag"] = tag
d, err = YAMLToJSON(data)
assert.NoError(t, err)
assert.Equal(t, `{"1":"the int key value","name":"a string value","tag":{"name":"tag name"},"y":"some value"}`, string(d))
tag = make(map[interface{}]interface{})
tag[true] = "bool tag name"
data["tag"] = tag
d, err = YAMLToJSON(data)
assert.Error(t, err)
assert.Nil(t, d)
var lst []interface{}
lst = append(lst, "hello")
d, err = YAMLToJSON(lst)
assert.NoError(t, err)
assert.Equal(t, []byte(`["hello"]`), []byte(d))
lst = append(lst, data)
d, err = YAMLToJSON(lst)
assert.Error(t, err)
assert.Nil(t, d)
// _, err := yamlToJSON(failJSONMarhal{})
// assert.Error(t, err)
_, err = BytesToYAMLDoc([]byte("- name: hello\n"))
assert.Error(t, err)
dd, err := BytesToYAMLDoc([]byte("description: 'object created'\n"))
assert.NoError(t, err)
d, err = YAMLToJSON(dd)
assert.NoError(t, err)
assert.Equal(t, json.RawMessage(`{"description":"object created"}`), d)
}
func TestLoadStrategy(t *testing.T) {
loader := func(p string) ([]byte, error) {
return []byte(yamlPetStore), nil
}
remLoader := func(p string) ([]byte, error) {
return []byte("not it"), nil
}
ld := swag.LoadStrategy("blah", loader, remLoader)
b, _ := ld("")
assert.Equal(t, []byte(yamlPetStore), b)
serv := httptest.NewServer(http.HandlerFunc(yamlPestoreServer))
defer serv.Close()
s, err := YAMLDoc(serv.URL)
assert.NoError(t, err)
assert.NotNil(t, s)
ts2 := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusNotFound)
rw.Write([]byte("\n"))
}))
defer ts2.Close()
_, err = YAMLDoc(ts2.URL)
assert.Error(t, err)
}
var yamlPestoreServer = func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(http.StatusOK)
rw.Write([]byte(yamlPetStore))
}
func TestWithYKey(t *testing.T) {
doc, err := BytesToYAMLDoc([]byte(withYKey))
if assert.NoError(t, err) {
_, err := YAMLToJSON(doc)
if assert.Error(t, err) {
doc, err := BytesToYAMLDoc([]byte(withQuotedYKey))
if assert.NoError(t, err) {
jsond, err := YAMLToJSON(doc)
if assert.NoError(t, err) {
var yt struct {
Definitions struct {
Viewbox struct {
Properties struct {
Y struct {
Type string `json:"type"`
} `json:"y"`
} `json:"properties"`
} `json:"viewbox"`
} `json:"definitions"`
}
if assert.NoError(t, json.Unmarshal(jsond, &yt)) {
assert.Equal(t, "integer", yt.Definitions.Viewbox.Properties.Y.Type)
}
}
}
}
}
}
const withQuotedYKey = `consumes:
- application/json
definitions:
viewBox:
type: object
properties:
x:
type: integer
format: int16
# y -> types don't match: expect map key string or int get: bool
"y":
type: integer
format: int16
width:
type: integer
format: int16
height:
type: integer
format: int16
info:
description: Test RESTful APIs
title: Test Server
version: 1.0.0
basePath: /api
paths:
/test:
get:
operationId: findAll
parameters:
- name: since
in: query
type: integer
format: int64
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: Array[Trigger]
schema:
type: array
items:
$ref: "#/definitions/viewBox"
produces:
- application/json
schemes:
- https
swagger: "2.0"
`
const withYKey = `consumes:
- application/json
definitions:
viewBox:
type: object
properties:
x:
type: integer
format: int16
# y -> types don't match: expect map key string or int get: bool
y:
type: integer
format: int16
width:
type: integer
format: int16
height:
type: integer
format: int16
info:
description: Test RESTful APIs
title: Test Server
version: 1.0.0
basePath: /api
paths:
/test:
get:
operationId: findAll
parameters:
- name: since
in: query
type: integer
format: int64
- name: limit
in: query
type: integer
format: int32
default: 20
responses:
200:
description: Array[Trigger]
schema:
type: array
items:
$ref: "#/definitions/viewBox"
produces:
- application/json
schemes:
- https
swagger: "2.0"
`
const yamlPetStore = `swagger: '2.0'
info:
version: '1.0.0'
title: Swagger Petstore
description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
termsOfService: http://helloreverb.com/terms/
contact:
name: Swagger API team
email: foo@example.com
url: http://swagger.io
license:
name: MIT
url: http://opensource.org/licenses/MIT
host: petstore.swagger.wordnik.com
basePath: /api
schemes:
- http
consumes:
- application/json
produces:
- application/json
paths:
/pets:
get:
description: Returns all pets from the system that the user has access to
operationId: findPets
produces:
- application/json
- application/xml
- text/xml
- text/html
parameters:
- name: tags
in: query
description: tags to filter by
required: false
type: array
items:
type: string
collectionFormat: csv
- name: limit
in: query
description: maximum number of results to return
required: false
type: integer
format: int32
responses:
'200':
description: pet response
schema:
type: array
items:
$ref: '#/definitions/pet'
default:
description: unexpected error
schema:
$ref: '#/definitions/errorModel'
post:
description: Creates a new pet in the store. Duplicates are allowed
operationId: addPet
produces:
- application/json
parameters:
- name: pet
in: body
description: Pet to add to the store
required: true
schema:
$ref: '#/definitions/newPet'
responses:
'200':
description: pet response
schema:
$ref: '#/definitions/pet'
default:
description: unexpected error
schema:
$ref: '#/definitions/errorModel'
/pets/{id}:
get:
description: Returns a user based on a single ID, if the user does not have access to the pet
operationId: findPetById
produces:
- application/json
- application/xml
- text/xml
- text/html
parameters:
- name: id
in: path
description: ID of pet to fetch
required: true
type: integer
format: int64
responses:
'200':
description: pet response
schema:
$ref: '#/definitions/pet'
default:
description: unexpected error
schema:
$ref: '#/definitions/errorModel'
delete:
description: deletes a single pet based on the ID supplied
operationId: deletePet
parameters:
- name: id
in: path
description: ID of pet to delete
required: true
type: integer
format: int64
responses:
'204':
description: pet deleted
default:
description: unexpected error
schema:
$ref: '#/definitions/errorModel'
definitions:
pet:
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
newPet:
allOf:
- $ref: '#/definitions/pet'
- required:
- name
properties:
id:
type: integer
format: int64
name:
type: string
errorModel:
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
`