forked from LaconicNetwork/kompose
Merge pull request #324 from rtnpro/unsupported-keys-per-provider
Unsupported keys per provider
This commit is contained in:
commit
48e3ba88cd
@ -16,93 +16,15 @@ limitations under the License.
|
||||
|
||||
package kobject
|
||||
|
||||
import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/fatih/structs"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
var unsupportedKey = map[string]int{
|
||||
"Build": 0,
|
||||
"CgroupParent": 0,
|
||||
"Devices": 0,
|
||||
"DependsOn": 0,
|
||||
"DNS": 0,
|
||||
"DNSSearch": 0,
|
||||
"DomainName": 0,
|
||||
"EnvFile": 0,
|
||||
"Extends": 0,
|
||||
"ExternalLinks": 0,
|
||||
"ExtraHosts": 0,
|
||||
"Hostname": 0,
|
||||
"Ipc": 0,
|
||||
"Logging": 0,
|
||||
"MacAddress": 0,
|
||||
"MemLimit": 0,
|
||||
"MemSwapLimit": 0,
|
||||
"NetworkMode": 0,
|
||||
"Pid": 0,
|
||||
"SecurityOpt": 0,
|
||||
"ShmSize": 0,
|
||||
"StopSignal": 0,
|
||||
"VolumeDriver": 0,
|
||||
"Uts": 0,
|
||||
"ReadOnly": 0,
|
||||
"StdinOpen": 0,
|
||||
"Tty": 0,
|
||||
"Ulimits": 0,
|
||||
"Dockerfile": 0,
|
||||
"Net": 0,
|
||||
"Networks": 0,
|
||||
}
|
||||
|
||||
var composeOptions = map[string]string{
|
||||
"Build": "build",
|
||||
"CapAdd": "cap_add",
|
||||
"CapDrop": "cap_drop",
|
||||
"CPUSet": "cpuset",
|
||||
"CPUShares": "cpu_shares",
|
||||
"CPUQuota": "cpu_quota",
|
||||
"CgroupParent": "cgroup_parent",
|
||||
"Devices": "devices",
|
||||
"DependsOn": "depends_on",
|
||||
"DNS": "dns",
|
||||
"DNSSearch": "dns_search",
|
||||
"DomainName": "domainname",
|
||||
"Entrypoint": "entrypoint",
|
||||
"EnvFile": "env_file",
|
||||
"Expose": "expose",
|
||||
"Extends": "extends",
|
||||
"ExternalLinks": "external_links",
|
||||
"ExtraHosts": "extra_hosts",
|
||||
"Hostname": "hostname",
|
||||
"Ipc": "ipc",
|
||||
"Logging": "logging",
|
||||
"MacAddress": "mac_address",
|
||||
"MemLimit": "mem_limit",
|
||||
"MemSwapLimit": "memswap_limit",
|
||||
"NetworkMode": "network_mode",
|
||||
"Networks": "networks",
|
||||
"Pid": "pid",
|
||||
"SecurityOpt": "security_opt",
|
||||
"ShmSize": "shm_size",
|
||||
"StopSignal": "stop_signal",
|
||||
"VolumeDriver": "volume_driver",
|
||||
"VolumesFrom": "volumes_from",
|
||||
"Uts": "uts",
|
||||
"ReadOnly": "read_only",
|
||||
"StdinOpen": "stdin_open",
|
||||
"Tty": "tty",
|
||||
"User": "user",
|
||||
"Ulimits": "ulimits",
|
||||
"Dockerfile": "dockerfile",
|
||||
"Net": "net",
|
||||
"Args": "args",
|
||||
}
|
||||
import "k8s.io/kubernetes/pkg/api"
|
||||
|
||||
// KomposeObject holds the generic struct of Kompose transformation
|
||||
type KomposeObject struct {
|
||||
ServiceConfigs map[string]ServiceConfig
|
||||
// LoadedFrom is name of the loader that created KomposeObject
|
||||
// Transformer need to know origin format in order to tell user what tag is not supported in origin format
|
||||
// as they can have different names. For example environment variables are called environment in compose but Env in bundle.
|
||||
LoadedFrom string
|
||||
}
|
||||
|
||||
type ConvertOptions struct {
|
||||
@ -122,28 +44,30 @@ type ConvertOptions struct {
|
||||
|
||||
// ServiceConfig holds the basic struct of a container
|
||||
type ServiceConfig struct {
|
||||
// use tags to mark from what element this value comes
|
||||
ContainerName string
|
||||
Image string
|
||||
Environment []EnvVar
|
||||
Port []Ports
|
||||
Command []string
|
||||
WorkingDir string
|
||||
Args []string
|
||||
Volumes []string
|
||||
Network []string
|
||||
Labels map[string]string
|
||||
Annotations map[string]string
|
||||
CPUSet string
|
||||
CPUShares int64
|
||||
CPUQuota int64
|
||||
CapAdd []string
|
||||
CapDrop []string
|
||||
Expose []string
|
||||
Privileged bool
|
||||
Restart string
|
||||
User string
|
||||
VolumesFrom []string
|
||||
ServiceType string
|
||||
Image string `compose:"image",bundle:"Image"`
|
||||
Environment []EnvVar `compose:"environment",bundle:"Env"`
|
||||
Port []Ports `compose:"ports",bundle:"Ports"`
|
||||
Command []string `compose:"command",bundle:"Command"`
|
||||
WorkingDir string `compose:"",bundle:"WorkingDir"`
|
||||
Args []string `compose:"args",bundle:"Args"`
|
||||
Volumes []string `compose:"volumes",bundle:"Volumes"`
|
||||
Network []string `compose:"network",bundle:"Networks"`
|
||||
Labels map[string]string `compose:"labels",bundle:"Labels"`
|
||||
Annotations map[string]string `compose:"",bundle:""`
|
||||
CPUSet string `compose:"cpuset",bundle:""`
|
||||
CPUShares int64 `compose:"cpu_shares",bundle:""`
|
||||
CPUQuota int64 `compose:"cpu_quota",bundle:""`
|
||||
CapAdd []string `compose:"cap_add",bundle:""`
|
||||
CapDrop []string `compose:"cap_drop",bundle:""`
|
||||
Expose []string `compose:"expose",bundle:""`
|
||||
Privileged bool `compose:"privileged",bundle:""`
|
||||
Restart string `compose:"restart",bundle:""`
|
||||
User string `compose:"user",bundle:"User"`
|
||||
VolumesFrom []string `compose:"volumes_from",bundle:""`
|
||||
ServiceType string `compose:"kompose.service.type",bundle:""`
|
||||
Build string `compose:"build",bundle:""`
|
||||
}
|
||||
|
||||
// EnvVar holds the environment variable struct of a container
|
||||
@ -158,15 +82,3 @@ type Ports struct {
|
||||
ContainerPort int32
|
||||
Protocol api.Protocol
|
||||
}
|
||||
|
||||
func CheckUnsupportedKey(service interface{}) {
|
||||
s := structs.New(service)
|
||||
for _, f := range s.Fields() {
|
||||
if f.IsExported() && !f.IsZero() && f.Name() != "Networks" {
|
||||
if count, ok := unsupportedKey[f.Name()]; ok && count == 0 {
|
||||
logrus.Warningf("Unsupported key %s - ignoring", composeOptions[f.Name()])
|
||||
unsupportedKey[f.Name()]++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,11 +21,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kubernetes-incubator/kompose/pkg/kobject"
|
||||
)
|
||||
|
||||
@ -57,6 +59,51 @@ type Port struct {
|
||||
Port uint32
|
||||
}
|
||||
|
||||
// checkUnsupportedKey checks if dab contains
|
||||
// keys that are not supported by this loader.
|
||||
// list of all unsupported keys are stored in unsupportedKey variable
|
||||
// returns list of unsupported JSON/YAML keys
|
||||
func checkUnsupportedKey(bundleStruct *Bundlefile) []string {
|
||||
// list of all unsupported keys for this loader
|
||||
// this is map to make searching for keys easier
|
||||
// to make sure that unsupported key is not going to be reported twice
|
||||
// by keeping record if already saw this key in another service
|
||||
var unsupportedKey = map[string]bool{
|
||||
"Networks": false,
|
||||
}
|
||||
|
||||
// collect all keys found in project
|
||||
var keysFound []string
|
||||
for _, service := range bundleStruct.Services {
|
||||
// this reflection is used in check for empty arrays
|
||||
val := reflect.ValueOf(service)
|
||||
s := structs.New(service)
|
||||
|
||||
for _, f := range s.Fields() {
|
||||
// Check if given key is among unsupported keys, and skip it if we already saw this key
|
||||
if alreadySaw, ok := unsupportedKey[f.Name()]; ok && !alreadySaw {
|
||||
if f.IsExported() && !f.IsZero() {
|
||||
jsonTagName := strings.Split(f.Tag("json"), ",")[0]
|
||||
if jsonTagName == "" {
|
||||
jsonTagName = f.Name()
|
||||
}
|
||||
// IsZero returns false for empty array/slice ([])
|
||||
// this check if field is Slice, and then it checks its size
|
||||
if field := val.FieldByName(f.Name()); field.Kind() == reflect.Slice {
|
||||
if field.Len() == 0 {
|
||||
// array is empty it doesn't matter if it is in unsupportedKey or not
|
||||
continue
|
||||
}
|
||||
}
|
||||
keysFound = append(keysFound, jsonTagName)
|
||||
unsupportedKey[f.Name()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return keysFound
|
||||
}
|
||||
|
||||
// load image from dab file
|
||||
func loadImage(service Service) (string, string) {
|
||||
character := "@"
|
||||
@ -129,6 +176,7 @@ func loadPorts(service Service) ([]kobject.Ports, string) {
|
||||
func (b *Bundle) LoadFile(file string) kobject.KomposeObject {
|
||||
komposeObject := kobject.KomposeObject{
|
||||
ServiceConfigs: make(map[string]kobject.ServiceConfig),
|
||||
LoadedFrom: "bundle",
|
||||
}
|
||||
|
||||
buf, err := ioutil.ReadFile(file)
|
||||
@ -141,8 +189,12 @@ func (b *Bundle) LoadFile(file string) kobject.KomposeObject {
|
||||
logrus.Fatalf("Failed to parse bundles file: %s", err)
|
||||
}
|
||||
|
||||
noSupKeys := checkUnsupportedKey(bundle)
|
||||
for _, keyName := range noSupKeys {
|
||||
logrus.Warningf("Unsupported %s key - ignoring", keyName)
|
||||
}
|
||||
|
||||
for name, service := range bundle.Services {
|
||||
kobject.CheckUnsupportedKey(service)
|
||||
|
||||
serviceConfig := kobject.ServiceConfig{}
|
||||
serviceConfig.Command = service.Command
|
||||
|
||||
87
pkg/loader/bundle/bundle_test.go
Normal file
87
pkg/loader/bundle/bundle_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors 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 bundle
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestUnsupportedKeys test checkUnsupportedKey function with various
|
||||
// docker-compose projects
|
||||
func TestUnsupportedKeys(t *testing.T) {
|
||||
user := "user"
|
||||
workDir := "workDir"
|
||||
|
||||
fullBundle := Bundlefile{
|
||||
Version: "0.1",
|
||||
Services: map[string]Service{
|
||||
"foo": Service{
|
||||
Image: "image",
|
||||
Command: []string{"cmd"},
|
||||
Args: []string{"arg"},
|
||||
Env: []string{"env"},
|
||||
Labels: map[string]string{"key": "value"},
|
||||
Ports: []Port{Port{Protocol: "tcp", Port: uint32(80)}},
|
||||
WorkingDir: &workDir, //there is no other way to get pointer to string
|
||||
User: &user,
|
||||
Networks: []string{"net"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
bundleWithEmptyNetworks := Bundlefile{
|
||||
Version: "0.1",
|
||||
Services: map[string]Service{
|
||||
"foo": Service{
|
||||
Image: "image",
|
||||
Command: []string{"cmd"},
|
||||
Args: []string{"arg"},
|
||||
Env: []string{"env"},
|
||||
Labels: map[string]string{"key": "value"},
|
||||
Ports: []Port{Port{Protocol: "tcp", Port: uint32(80)}},
|
||||
WorkingDir: &workDir, //there is no other way to get pointer to string
|
||||
User: &user,
|
||||
Networks: []string{},
|
||||
},
|
||||
},
|
||||
}
|
||||
// define all test cases for checkUnsupportedKey function
|
||||
testCases := map[string]struct {
|
||||
bundleFile Bundlefile
|
||||
expectedUnsupportedKeys []string
|
||||
}{
|
||||
"Full Bundle": {
|
||||
fullBundle,
|
||||
[]string{"Networks"},
|
||||
},
|
||||
"Bundle with empty Networks": {
|
||||
bundleWithEmptyNetworks,
|
||||
[]string(nil),
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range testCases {
|
||||
t.Log("Test case:", name)
|
||||
keys := checkUnsupportedKey(&test.bundleFile)
|
||||
if !reflect.DeepEqual(keys, test.expectedUnsupportedKeys) {
|
||||
t.Errorf("ERROR: Expecting unsupported keys: ['%s']. Got: ['%s']", strings.Join(test.expectedUnsupportedKeys, "', '"), strings.Join(keys, "', '"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@ -29,12 +30,105 @@ import (
|
||||
"github.com/docker/libcompose/config"
|
||||
"github.com/docker/libcompose/lookup"
|
||||
"github.com/docker/libcompose/project"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kubernetes-incubator/kompose/pkg/kobject"
|
||||
)
|
||||
|
||||
type Compose struct {
|
||||
}
|
||||
|
||||
// checkUnsupportedKey checks if libcompose project contains
|
||||
// keys that are not supported by this loader.
|
||||
// list of all unsupported keys are stored in unsupportedKey variable
|
||||
// returns list of unsupported YAML keys from docker-compose
|
||||
func checkUnsupportedKey(composeProject *project.Project) []string {
|
||||
|
||||
// list of all unsupported keys for this loader
|
||||
// this is map to make searching for keys easier
|
||||
// to make sure that unsupported key is not going to be reported twice
|
||||
// by keeping record if already saw this key in another service
|
||||
var unsupportedKey = map[string]bool{
|
||||
"CgroupParent": false,
|
||||
"Devices": false,
|
||||
"DependsOn": false,
|
||||
"DNS": false,
|
||||
"DNSSearch": false,
|
||||
"DomainName": false,
|
||||
"EnvFile": false,
|
||||
"Extends": false,
|
||||
"ExternalLinks": false,
|
||||
"ExtraHosts": false,
|
||||
"Hostname": false,
|
||||
"Ipc": false,
|
||||
"Logging": false,
|
||||
"MacAddress": false,
|
||||
"MemLimit": false,
|
||||
"MemSwapLimit": false,
|
||||
"NetworkMode": false,
|
||||
"Pid": false,
|
||||
"SecurityOpt": false,
|
||||
"ShmSize": false,
|
||||
"StopSignal": false,
|
||||
"VolumeDriver": false,
|
||||
"Uts": false,
|
||||
"ReadOnly": false,
|
||||
"StdinOpen": false,
|
||||
"Tty": false,
|
||||
"Ulimits": false,
|
||||
"Dockerfile": false,
|
||||
"Net": false,
|
||||
"Networks": false, // there are special checks for Network in checkUnsupportedKey function
|
||||
}
|
||||
|
||||
// collect all keys found in project
|
||||
var keysFound []string
|
||||
|
||||
// Root level keys
|
||||
// volume config and network config are not supported
|
||||
if len(composeProject.NetworkConfigs) > 0 {
|
||||
keysFound = append(keysFound, "root level networks")
|
||||
}
|
||||
if len(composeProject.VolumeConfigs) > 0 {
|
||||
keysFound = append(keysFound, "root level volumes")
|
||||
}
|
||||
|
||||
for _, serviceConfig := range composeProject.ServiceConfigs.All() {
|
||||
// this reflection is used in check for empty arrays
|
||||
val := reflect.ValueOf(serviceConfig).Elem()
|
||||
s := structs.New(serviceConfig)
|
||||
|
||||
for _, f := range s.Fields() {
|
||||
// Check if given key is among unsupported keys, and skip it if we already saw this key
|
||||
if alreadySaw, ok := unsupportedKey[f.Name()]; ok && !alreadySaw {
|
||||
if f.IsExported() && !f.IsZero() {
|
||||
// IsZero returns false for empty array/slice ([])
|
||||
// this check if field is Slice, and then it checks its size
|
||||
if field := val.FieldByName(f.Name()); field.Kind() == reflect.Slice {
|
||||
if field.Len() == 0 {
|
||||
// array is empty it doesn't matter if it is in unsupportedKey or not
|
||||
continue
|
||||
}
|
||||
}
|
||||
//get yaml tag name instad of variable name
|
||||
yamlTagName := strings.Split(f.Tag("yaml"), ",")[0]
|
||||
if f.Name() == "Networks" {
|
||||
// networks always contains one default element, even it isn't declared in compose v2.
|
||||
if len(serviceConfig.Networks.Networks) == 1 && serviceConfig.Networks.Networks[0].Name == "default" {
|
||||
// this is empty Network definition, skip it
|
||||
continue
|
||||
} else {
|
||||
yamlTagName = "networks"
|
||||
}
|
||||
}
|
||||
keysFound = append(keysFound, yamlTagName)
|
||||
unsupportedKey[f.Name()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return keysFound
|
||||
}
|
||||
|
||||
// load environment variables from compose file
|
||||
func loadEnvVars(envars []string) []kobject.EnvVar {
|
||||
envs := []kobject.EnvVar{}
|
||||
@ -132,6 +226,7 @@ func loadPorts(composePorts []string) ([]kobject.Ports, error) {
|
||||
func (c *Compose) LoadFile(file string) kobject.KomposeObject {
|
||||
komposeObject := kobject.KomposeObject{
|
||||
ServiceConfigs: make(map[string]kobject.ServiceConfig),
|
||||
LoadedFrom: "compose",
|
||||
}
|
||||
context := &project.Context{}
|
||||
if file == "" {
|
||||
@ -168,31 +263,19 @@ func (c *Compose) LoadFile(file string) kobject.KomposeObject {
|
||||
// transform composeObject into komposeObject
|
||||
composeServiceNames := composeObject.ServiceConfigs.Keys()
|
||||
|
||||
// volume config and network config are not supported
|
||||
if len(composeObject.NetworkConfigs) > 0 {
|
||||
logrus.Warningf("Unsupported network configuration of compose v2 - ignoring")
|
||||
noSupKeys := checkUnsupportedKey(composeObject)
|
||||
for _, keyName := range noSupKeys {
|
||||
logrus.Warningf("Unsupported %s key - ignoring", keyName)
|
||||
}
|
||||
if len(composeObject.VolumeConfigs) > 0 {
|
||||
logrus.Warningf("Unsupported volume configuration of compose v2 - ignoring")
|
||||
}
|
||||
|
||||
networksWarningFound := false
|
||||
|
||||
for _, name := range composeServiceNames {
|
||||
if composeServiceConfig, ok := composeObject.ServiceConfigs.Get(name); ok {
|
||||
//FIXME: networks always contains one default element, even it isn't declared in compose v2.
|
||||
if composeServiceConfig.Networks != nil && len(composeServiceConfig.Networks.Networks) > 0 &&
|
||||
composeServiceConfig.Networks.Networks[0].Name != "default" &&
|
||||
!networksWarningFound {
|
||||
logrus.Warningf("Unsupported key networks - ignoring")
|
||||
networksWarningFound = true
|
||||
}
|
||||
kobject.CheckUnsupportedKey(composeServiceConfig)
|
||||
serviceConfig := kobject.ServiceConfig{}
|
||||
serviceConfig.Image = composeServiceConfig.Image
|
||||
serviceConfig.ContainerName = composeServiceConfig.ContainerName
|
||||
serviceConfig.Command = composeServiceConfig.Entrypoint
|
||||
serviceConfig.Args = composeServiceConfig.Command
|
||||
serviceConfig.Build = composeServiceConfig.Build.Context
|
||||
|
||||
envs := loadEnvVars(composeServiceConfig.Environment)
|
||||
serviceConfig.Environment = envs
|
||||
|
||||
@ -18,9 +18,15 @@ package compose
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kubernetes-incubator/kompose/pkg/kobject"
|
||||
|
||||
"github.com/docker/libcompose/config"
|
||||
"github.com/docker/libcompose/project"
|
||||
"github.com/docker/libcompose/yaml"
|
||||
)
|
||||
|
||||
// Test if service types are parsed properly on user input
|
||||
@ -112,3 +118,98 @@ func TestLoadEnvVar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnsupportedKeys test checkUnsupportedKey function with various
|
||||
// docker-compose projects
|
||||
func TestUnsupportedKeys(t *testing.T) {
|
||||
// create project that will be used in test cases
|
||||
projectWithNetworks := project.NewProject(&project.Context{}, nil, nil)
|
||||
projectWithNetworks.ServiceConfigs = config.NewServiceConfigs()
|
||||
projectWithNetworks.ServiceConfigs.Add("foo", &config.ServiceConfig{
|
||||
Image: "foo/bar",
|
||||
Build: yaml.Build{
|
||||
Context: "./build",
|
||||
},
|
||||
Hostname: "localhost",
|
||||
Ports: []string{}, // test empty array
|
||||
Networks: &yaml.Networks{
|
||||
Networks: []*yaml.Network{
|
||||
&yaml.Network{
|
||||
Name: "net1",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
projectWithNetworks.ServiceConfigs.Add("bar", &config.ServiceConfig{
|
||||
Image: "bar/foo",
|
||||
Build: yaml.Build{
|
||||
Context: "./build",
|
||||
},
|
||||
Hostname: "localhost",
|
||||
Ports: []string{}, // test empty array
|
||||
Networks: &yaml.Networks{
|
||||
Networks: []*yaml.Network{
|
||||
&yaml.Network{
|
||||
Name: "net1",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
projectWithNetworks.VolumeConfigs = map[string]*config.VolumeConfig{
|
||||
"foo": &config.VolumeConfig{
|
||||
Driver: "storage",
|
||||
},
|
||||
}
|
||||
projectWithNetworks.NetworkConfigs = map[string]*config.NetworkConfig{
|
||||
"foo": &config.NetworkConfig{
|
||||
Driver: "bridge",
|
||||
},
|
||||
}
|
||||
|
||||
projectWithEmptyNetwork := project.NewProject(&project.Context{}, nil, nil)
|
||||
projectWithEmptyNetwork.ServiceConfigs = config.NewServiceConfigs()
|
||||
projectWithEmptyNetwork.ServiceConfigs.Add("foo", &config.ServiceConfig{
|
||||
Networks: &yaml.Networks{},
|
||||
})
|
||||
|
||||
projectWithDefaultNetwork := project.NewProject(&project.Context{}, nil, nil)
|
||||
projectWithDefaultNetwork.ServiceConfigs = config.NewServiceConfigs()
|
||||
|
||||
projectWithDefaultNetwork.ServiceConfigs.Add("foo", &config.ServiceConfig{
|
||||
Networks: &yaml.Networks{
|
||||
Networks: []*yaml.Network{
|
||||
&yaml.Network{
|
||||
Name: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// define all test cases for checkUnsupportedKey function
|
||||
testCases := map[string]struct {
|
||||
composeProject *project.Project
|
||||
expectedUnsupportedKeys []string
|
||||
}{
|
||||
"With Networks (service and root level)": {
|
||||
projectWithNetworks,
|
||||
[]string{"root level networks", "root level volumes", "hostname", "networks"},
|
||||
},
|
||||
"Empty Networks on Service level": {
|
||||
projectWithEmptyNetwork,
|
||||
[]string{"networks"},
|
||||
},
|
||||
"Default root level Network": {
|
||||
projectWithDefaultNetwork,
|
||||
[]string(nil),
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range testCases {
|
||||
t.Log("Test case:", name)
|
||||
keys := checkUnsupportedKey(test.composeProject)
|
||||
if !reflect.DeepEqual(keys, test.expectedUnsupportedKeys) {
|
||||
t.Errorf("ERROR: Expecting unsupported keys: ['%s']. Got: ['%s']", strings.Join(test.expectedUnsupportedKeys, "', '"), strings.Join(keys, "', '"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import (
|
||||
|
||||
type Loader interface {
|
||||
LoadFile(file string) kobject.KomposeObject
|
||||
///Name() string
|
||||
}
|
||||
|
||||
// GetLoader returns loader for given format
|
||||
|
||||
@ -18,11 +18,13 @@ package kubernetes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kubernetes-incubator/kompose/pkg/kobject"
|
||||
"github.com/kubernetes-incubator/kompose/pkg/transformer"
|
||||
deployapi "github.com/openshift/origin/pkg/deploy/api"
|
||||
@ -52,6 +54,52 @@ type Kubernetes struct {
|
||||
// used when undeploying resources from kubernetes
|
||||
const TIMEOUT = 300
|
||||
|
||||
// list of all unsupported keys for this transformer
|
||||
// Keys are names of variables in kobject struct.
|
||||
// this is map to make searching for keys easier
|
||||
// to make sure that unsupported key is not going to be reported twice
|
||||
// by keeping record if already saw this key in another service
|
||||
var unsupportedKey = map[string]bool{
|
||||
"Build": false,
|
||||
}
|
||||
|
||||
// checkUnsupportedKey checks if given komposeObject contains
|
||||
// keys that are not supported by this tranfomer.
|
||||
// list of all unsupported keys are stored in unsupportedKey variable
|
||||
// returns list of TODO: ....
|
||||
func (k *Kubernetes) CheckUnsupportedKey(komposeObject *kobject.KomposeObject, unsupportedKey map[string]bool) []string {
|
||||
// collect all keys found in project
|
||||
var keysFound []string
|
||||
|
||||
for _, serviceConfig := range komposeObject.ServiceConfigs {
|
||||
// this reflection is used in check for empty arrays
|
||||
val := reflect.ValueOf(serviceConfig)
|
||||
s := structs.New(serviceConfig)
|
||||
|
||||
for _, f := range s.Fields() {
|
||||
// Check if given key is among unsupported keys, and skip it if we already saw this key
|
||||
if alreadySaw, ok := unsupportedKey[f.Name()]; ok && !alreadySaw {
|
||||
|
||||
if f.IsExported() && !f.IsZero() {
|
||||
// IsZero returns false for empty array/slice ([])
|
||||
// this check if field is Slice, and then it checks its size
|
||||
if field := val.FieldByName(f.Name()); field.Kind() == reflect.Slice {
|
||||
if field.Len() == 0 {
|
||||
// array is empty it doesn't matter if it is in unsupportedKey or not
|
||||
continue
|
||||
}
|
||||
}
|
||||
//get tag from kobject service configure
|
||||
tag := f.Tag(komposeObject.LoadedFrom)
|
||||
keysFound = append(keysFound, tag)
|
||||
unsupportedKey[f.Name()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return keysFound
|
||||
}
|
||||
|
||||
// Init RC object
|
||||
func (k *Kubernetes) InitRC(name string, service kobject.ServiceConfig, replicas int) *api.ReplicationController {
|
||||
rc := &api.ReplicationController{
|
||||
@ -351,6 +399,12 @@ func (k *Kubernetes) InitPod(name string, service kobject.ServiceConfig) *api.Po
|
||||
// Transform maps komposeObject to k8s objects
|
||||
// returns object that are already sorted in the way that Services are first
|
||||
func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
|
||||
|
||||
noSupKeys := k.CheckUnsupportedKey(&komposeObject, unsupportedKey)
|
||||
for _, keyName := range noSupKeys {
|
||||
logrus.Warningf("Kubernetes provider doesn't support %s key - ignoring", keyName)
|
||||
}
|
||||
|
||||
// this will hold all the converted data
|
||||
var allobjects []runtime.Object
|
||||
|
||||
|
||||
@ -18,6 +18,8 @@ package kubernetes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
deployapi "github.com/openshift/origin/pkg/deploy/api"
|
||||
@ -353,3 +355,36 @@ func TestConvertRestartOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestUnsupportedKeys test checkUnsupportedKey function
|
||||
func TestUnsupportedKeys(t *testing.T) {
|
||||
|
||||
kobjectWithBuild := newKomposeObject()
|
||||
kobjectWithBuild.LoadedFrom = "compose"
|
||||
serviceConfig := kobjectWithBuild.ServiceConfigs["app"]
|
||||
serviceConfig.Build = "./asdf"
|
||||
serviceConfig.Network = []string{}
|
||||
kobjectWithBuild.ServiceConfigs = map[string]kobject.ServiceConfig{"app": serviceConfig}
|
||||
|
||||
// define all test cases for checkUnsupportedKey function
|
||||
testCases := map[string]struct {
|
||||
bundleFile kobject.KomposeObject
|
||||
expectedUnsupportedKeys []string
|
||||
}{
|
||||
"Full Bundle": {
|
||||
kobjectWithBuild,
|
||||
[]string{"build"},
|
||||
},
|
||||
}
|
||||
|
||||
k := Kubernetes{}
|
||||
|
||||
for name, test := range testCases {
|
||||
t.Log("Test case:", name)
|
||||
keys := k.CheckUnsupportedKey(&test.bundleFile, unsupportedKey)
|
||||
if !reflect.DeepEqual(keys, test.expectedUnsupportedKeys) {
|
||||
t.Errorf("ERROR: Expecting unsupported keys: ['%s']. Got: ['%s']", strings.Join(test.expectedUnsupportedKeys, "', '"), strings.Join(keys, "', '"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -33,11 +33,12 @@ import (
|
||||
oclient "github.com/openshift/origin/pkg/client"
|
||||
ocliconfig "github.com/openshift/origin/pkg/cmd/cli/config"
|
||||
|
||||
"time"
|
||||
|
||||
deployapi "github.com/openshift/origin/pkg/deploy/api"
|
||||
deploymentconfigreaper "github.com/openshift/origin/pkg/deploy/cmd"
|
||||
imageapi "github.com/openshift/origin/pkg/image/api"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OpenShift struct {
|
||||
@ -51,6 +52,13 @@ type OpenShift struct {
|
||||
// used when undeploying resources from OpenShift
|
||||
const TIMEOUT = 300
|
||||
|
||||
// list of all unsupported keys for this transformer
|
||||
// Keys are names of variables in kobject struct.
|
||||
// this is map to make searching for keys easier
|
||||
// to make sure that unsupported key is not going to be reported twice
|
||||
// by keeping record if already saw this key in another service
|
||||
var unsupportedKey = map[string]bool{}
|
||||
|
||||
// getImageTag get tag name from image name
|
||||
// if no tag is specified return 'latest'
|
||||
func getImageTag(image string) string {
|
||||
@ -151,6 +159,10 @@ func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceCon
|
||||
// Transform maps komposeObject to openshift objects
|
||||
// returns objects that are already sorted in the way that Services are first
|
||||
func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
|
||||
noSupKeys := o.Kubernetes.CheckUnsupportedKey(&komposeObject, unsupportedKey)
|
||||
for _, keyName := range noSupKeys {
|
||||
logrus.Warningf("OpenShift provider doesn't support %s key - ignoring", keyName)
|
||||
}
|
||||
// this will hold all the converted data
|
||||
var allobjects []runtime.Object
|
||||
|
||||
|
||||
@ -26,9 +26,9 @@ convert::expect_failure "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/
|
||||
convert::expect_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose-no-ports.yml convert --stdout" "Service cannot be created because of missing port."
|
||||
export $(cat $KOMPOSE_ROOT/script/test/fixtures/etherpad/envs)
|
||||
# kubernetes test
|
||||
convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/etherpad/output-k8s.json" "Unsupported key depends_on - ignoring"
|
||||
convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/etherpad/output-k8s.json" "Unsupported depends_on key - ignoring"
|
||||
# openshift test
|
||||
convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/etherpad/output-os.json" "Unsupported key depends_on - ignoring"
|
||||
convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/etherpad/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/etherpad/output-os.json" "Unsupported depends_on key - ignoring"
|
||||
unset $(cat $KOMPOSE_ROOT/script/test/fixtures/etherpad/envs | cut -d'=' -f1)
|
||||
|
||||
######
|
||||
@ -44,10 +44,9 @@ unset $(cat $KOMPOSE_ROOT/script/test/fixtures/gitlab/envs | cut -d'=' -f1)
|
||||
######
|
||||
# Tests related to docker-compose file in /script/test/fixtures/ngnix-node-redis
|
||||
# kubernetes test
|
||||
convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/output-k8s.json" "Unsupported key build - ignoring"
|
||||
convert::expect_success_and_warning "kompose -f $KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/output-k8s.json" "Kubernetes provider doesn't support build key - ignoring"
|
||||
# openshift test
|
||||
convert::expect_success_and_warning "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/output-os.json" "Unsupported key build - ignoring"
|
||||
|
||||
convert::expect_success "kompose --provider=openshift -f $KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/docker-compose.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/ngnix-node-redis/output-os.json"
|
||||
|
||||
######
|
||||
# Tests related to docker-compose file in /script/test/fixtures/entrypoint-command
|
||||
|
||||
Loading…
Reference in New Issue
Block a user