forked from LaconicNetwork/kompose
Remove code for parsing DAB files (#1435)
* Remove code for parsing DAB files Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
This commit is contained in:
parent
a4c784d7ee
commit
41cd3108d9
@ -106,8 +106,7 @@ var convertCmd = &cobra.Command{
|
||||
MultipleContainerMode: MultipleContainerMode,
|
||||
}
|
||||
|
||||
// Validate before doing anything else. Use "bundle" if passed in.
|
||||
app.ValidateFlags(GlobalBundle, args, cmd, &ConvertOpt)
|
||||
app.ValidateFlags(args, cmd, &ConvertOpt)
|
||||
app.ValidateComposeFile(&ConvertOpt)
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
@ -39,7 +39,6 @@ func (errorOnWarningHook) Fire(entry *log.Entry) error {
|
||||
|
||||
// TODO: comment
|
||||
var (
|
||||
GlobalBundle string
|
||||
GlobalProvider string
|
||||
GlobalVerbose bool
|
||||
GlobalSuppressWarnings bool
|
||||
@ -95,10 +94,5 @@ func init() {
|
||||
RootCmd.PersistentFlags().BoolVar(&GlobalSuppressWarnings, "suppress-warnings", false, "Suppress all warnings")
|
||||
RootCmd.PersistentFlags().BoolVar(&GlobalErrorOnWarning, "error-on-warning", false, "Treat any warning as an error")
|
||||
RootCmd.PersistentFlags().StringArrayVarP(&GlobalFiles, "file", "f", []string{}, "Specify an alternative compose file")
|
||||
RootCmd.PersistentFlags().StringVarP(&GlobalBundle, "bundle", "b", "", "Specify a Distributed Application Bundle (DAB) file")
|
||||
RootCmd.PersistentFlags().StringVar(&GlobalProvider, "provider", "kubernetes", "Specify a provider. Kubernetes or OpenShift.")
|
||||
|
||||
// Mark DAB / bundle as deprecated, see issue: https://github.com/kubernetes/kompose/issues/390
|
||||
// As DAB is still EXPERIMENTAL
|
||||
RootCmd.PersistentFlags().MarkDeprecated("bundle", "DAB / Bundle is deprecated, see: https://github.com/kubernetes/kompose/issues/390")
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
## Loader
|
||||
|
||||
Loader reads input file (now `kompose` supports [Docker Compose](https://docs.docker.com/compose) v1, v2 and [Docker Distributed Application Bundle](https://blog.docker.com/2016/06/docker-app-bundle/) file) and converts it to KomposeObject.
|
||||
Loader reads input file (now `kompose` supports [Docker Compose](https://docs.docker.com/compose) v1, v2 and converts it to KomposeObject.
|
||||
|
||||
Loader is represented by a Loader interface:
|
||||
|
||||
@ -19,10 +19,9 @@ type Loader interface {
|
||||
}
|
||||
```
|
||||
|
||||
Every loader “implementation” should be placed into `kompose/pkg/loader` (like compose & bundle). More input formats will be supported in future. You can take a look for more details at:
|
||||
Every loader “implementation” should be placed into `kompose/pkg/loader` (like compose). More input formats will be supported in future. You can take a look for more details at:
|
||||
|
||||
* [kompose/pkg/loader](https://github.com/kubernetes/kompose/tree/master/pkg/loader)
|
||||
* [kompose/pkg/loader/bundle](https://github.com/kubernetes/kompose/tree/master/pkg/loader/bundle)
|
||||
* [kompose/pkg/loader/compose](https://github.com/kubernetes/kompose/tree/master/pkg/loader/compose)
|
||||
|
||||
## KomposeObject
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 122 KiB |
@ -53,10 +53,7 @@ const (
|
||||
var inputFormat = "compose"
|
||||
|
||||
// ValidateFlags validates all command line flags
|
||||
func ValidateFlags(bundle string, args []string, cmd *cobra.Command, opt *kobject.ConvertOptions) {
|
||||
// Check to see if the "file" has changed from the default flag value
|
||||
isFileSet := cmd.Flags().Lookup("file").Changed
|
||||
|
||||
func ValidateFlags(args []string, cmd *cobra.Command, opt *kobject.ConvertOptions) {
|
||||
if opt.OutFile == "-" {
|
||||
opt.ToStdout = true
|
||||
opt.OutFile = ""
|
||||
@ -127,16 +124,6 @@ func ValidateFlags(bundle string, args []string, cmd *cobra.Command, opt *kobjec
|
||||
log.Fatalf("Error: --replicas cannot be negative")
|
||||
}
|
||||
|
||||
if len(bundle) > 0 {
|
||||
inputFormat = "bundle"
|
||||
log.Fatalf("DAB / bundle (--bundle | -b) is no longer supported. See issue: https://github.com/kubernetes/kompose/issues/390")
|
||||
opt.InputFiles = []string{bundle}
|
||||
}
|
||||
|
||||
if len(bundle) > 0 && isFileSet {
|
||||
log.Fatalf("Error: 'compose' file and 'dab' file cannot be specified at the same time")
|
||||
}
|
||||
|
||||
if len(args) != 0 {
|
||||
log.Fatal("Unknown Argument(s): ", strings.Join(args, ","))
|
||||
}
|
||||
|
||||
@ -1,252 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
"github.com/kubernetes/kompose/pkg/kobject"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Bundle is docker bundle file loader, implements Loader interface
|
||||
type Bundle struct {
|
||||
}
|
||||
|
||||
// Bundlefile stores the contents of a bundlefile
|
||||
type Bundlefile struct {
|
||||
Version string
|
||||
Services map[string]Service
|
||||
}
|
||||
|
||||
// Service is a service from a bundlefile
|
||||
type Service struct {
|
||||
Image string
|
||||
Command []string `json:",omitempty"`
|
||||
Args []string `json:",omitempty"`
|
||||
Env []string `json:",omitempty"`
|
||||
Labels map[string]string `json:",omitempty"`
|
||||
Ports []Port `json:",omitempty"`
|
||||
WorkingDir *string `json:",omitempty"`
|
||||
User *string `json:",omitempty"`
|
||||
Networks []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Port is a port as defined in a bundlefile
|
||||
type Port struct {
|
||||
Protocol string
|
||||
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, error) {
|
||||
character := "@"
|
||||
if strings.Contains(service.Image, character) {
|
||||
return service.Image[0:strings.Index(service.Image, character)], nil
|
||||
}
|
||||
return "", errors.New("Invalid image format")
|
||||
}
|
||||
|
||||
// load environment variables from dab file
|
||||
func loadEnvVars(service Service) ([]kobject.EnvVar, error) {
|
||||
envs := []kobject.EnvVar{}
|
||||
for _, env := range service.Env {
|
||||
character := "="
|
||||
if strings.Contains(env, character) {
|
||||
value := env[strings.Index(env, character)+1:]
|
||||
name := env[0:strings.Index(env, character)]
|
||||
name = strings.TrimSpace(name)
|
||||
value = strings.TrimSpace(value)
|
||||
envs = append(envs, kobject.EnvVar{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
} else {
|
||||
character = ":"
|
||||
if strings.Contains(env, character) {
|
||||
charQuote := "'"
|
||||
value := env[strings.Index(env, character)+1:]
|
||||
name := env[0:strings.Index(env, character)]
|
||||
name = strings.TrimSpace(name)
|
||||
value = strings.TrimSpace(value)
|
||||
if strings.Contains(value, charQuote) {
|
||||
value = strings.Trim(value, "'")
|
||||
}
|
||||
envs = append(envs, kobject.EnvVar{
|
||||
Name: name,
|
||||
Value: value,
|
||||
})
|
||||
} else {
|
||||
return envs, errors.New("Invalid container env")
|
||||
}
|
||||
}
|
||||
}
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
// load ports from dab file
|
||||
func loadPorts(service Service) ([]kobject.Ports, error) {
|
||||
ports := []kobject.Ports{}
|
||||
for _, port := range service.Ports {
|
||||
komposePorts := kobject.Ports{
|
||||
HostPort: int32(port.Port),
|
||||
ContainerPort: int32(port.Port),
|
||||
Protocol: port.Protocol,
|
||||
}
|
||||
if protocol := api.Protocol(port.Protocol); protocol != api.ProtocolTCP && protocol != api.ProtocolUDP {
|
||||
komposePorts.Protocol = string(api.ProtocolTCP)
|
||||
}
|
||||
ports = append(ports, komposePorts)
|
||||
}
|
||||
return ports, nil
|
||||
}
|
||||
|
||||
// LoadFile loads dab file into KomposeObject
|
||||
func (b *Bundle) LoadFile(files []string) (kobject.KomposeObject, error) {
|
||||
komposeObject := kobject.KomposeObject{
|
||||
ServiceConfigs: make(map[string]kobject.ServiceConfig),
|
||||
LoadedFrom: "bundle",
|
||||
}
|
||||
file := files[0]
|
||||
buf, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return kobject.KomposeObject{}, errors.Wrap(err, "ioutil.ReadFile failed, Failed to read bundles file")
|
||||
}
|
||||
reader := strings.NewReader(string(buf))
|
||||
bundle, err := loadFile(reader)
|
||||
if err != nil {
|
||||
return kobject.KomposeObject{}, errors.Wrap(err, "loadFile failed, Failed to parse bundles file")
|
||||
}
|
||||
|
||||
noSupKeys := checkUnsupportedKey(bundle)
|
||||
for _, keyName := range noSupKeys {
|
||||
log.Warningf("Unsupported %s key - ignoring", keyName)
|
||||
}
|
||||
|
||||
for name, service := range bundle.Services {
|
||||
serviceConfig := kobject.ServiceConfig{}
|
||||
serviceConfig.Command = service.Command
|
||||
serviceConfig.Args = service.Args
|
||||
// convert bundle labels to annotations
|
||||
serviceConfig.Annotations = service.Labels
|
||||
|
||||
image, err := loadImage(service)
|
||||
if err != nil {
|
||||
return kobject.KomposeObject{}, errors.Wrap(err, "loadImage failed, Failed to load image from bundles file")
|
||||
}
|
||||
serviceConfig.Image = image
|
||||
|
||||
envs, err := loadEnvVars(service)
|
||||
if err != nil {
|
||||
return kobject.KomposeObject{}, errors.Wrap(err, "loadEnvVars failed, Failed to load envvar from bundles file")
|
||||
}
|
||||
serviceConfig.Environment = envs
|
||||
|
||||
ports, err := loadPorts(service)
|
||||
if err != nil {
|
||||
return kobject.KomposeObject{}, errors.Wrap(err, "loadPorts failed, Failed to load ports from bundles file")
|
||||
}
|
||||
serviceConfig.Port = ports
|
||||
|
||||
if service.WorkingDir != nil {
|
||||
serviceConfig.WorkingDir = *service.WorkingDir
|
||||
}
|
||||
|
||||
komposeObject.ServiceConfigs[name] = serviceConfig
|
||||
}
|
||||
|
||||
return komposeObject, nil
|
||||
}
|
||||
|
||||
// LoadFile loads a bundlefile from a path to the file
|
||||
func loadFile(reader io.Reader) (*Bundlefile, error) {
|
||||
bundlefile := &Bundlefile{}
|
||||
|
||||
decoder := json.NewDecoder(reader)
|
||||
if err := decoder.Decode(bundlefile); err != nil {
|
||||
switch jsonErr := err.(type) {
|
||||
case *json.SyntaxError:
|
||||
return nil, fmt.Errorf(
|
||||
"JSON syntax error at byte %v: %s",
|
||||
jsonErr.Offset,
|
||||
jsonErr.Error())
|
||||
case *json.UnmarshalTypeError:
|
||||
return nil, fmt.Errorf(
|
||||
"unexpected type at byte %v. expected %s but received %s",
|
||||
jsonErr.Offset,
|
||||
jsonErr.Type,
|
||||
jsonErr.Value)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return bundlefile, nil
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
/*
|
||||
Copyright 2017 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,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubernetes/kompose/pkg/kobject"
|
||||
"github.com/kubernetes/kompose/pkg/loader/bundle"
|
||||
"github.com/kubernetes/kompose/pkg/loader/compose"
|
||||
)
|
||||
|
||||
@ -32,16 +31,8 @@ type Loader interface {
|
||||
|
||||
// GetLoader returns loader for given format
|
||||
func GetLoader(format string) (Loader, error) {
|
||||
var l Loader
|
||||
|
||||
switch format {
|
||||
case "bundle":
|
||||
l = new(bundle.Bundle)
|
||||
case "compose":
|
||||
l = new(compose.Compose)
|
||||
default:
|
||||
if format != "compose" {
|
||||
return nil, fmt.Errorf("input file format %s is not supported", format)
|
||||
}
|
||||
|
||||
return l, nil
|
||||
return new(compose.Compose), nil
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user