-
Notifications
You must be signed in to change notification settings - Fork 129
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
764 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/kong/deck/convert" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var ( | ||
convertCmdSourceFormat string | ||
convertCmdDestinationFormat string | ||
convertCmdInputFile string | ||
convertCmdOutputFile string | ||
) | ||
|
||
// convertCmd represents the convert command | ||
var convertCmd = &cobra.Command{ | ||
Use: "convert", | ||
Short: "Convert files in one format to another format", | ||
Long: `Convert command converts files representing configuration in one format | ||
to another compatible format. For example: a configuration for 'kong-gateway' | ||
can be converted into 'konnect' configuration file.`, | ||
Args: validateNoArgs, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
sourceFormat, err := convert.ParseFormat(convertCmdSourceFormat) | ||
if err != nil { | ||
return err | ||
} | ||
destinationFormat, err := convert.ParseFormat(convertCmdDestinationFormat) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if yes, err := confirmFileOverwrite(convertCmdOutputFile, "", false); err != nil { | ||
return err | ||
} else if !yes { | ||
return nil | ||
} | ||
|
||
err = convert.Convert(convertCmdInputFile, convertCmdOutputFile, sourceFormat, destinationFormat) | ||
if err != nil { | ||
return fmt.Errorf("converting file: %v", err) | ||
} | ||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
convertCmd.Flags().StringVar(&convertCmdSourceFormat, "from", "", | ||
fmt.Sprintf("format of the source file, allowed formats:%v", convert.AllFormats)) | ||
convertCmd.Flags().StringVar(&convertCmdDestinationFormat, "to", "", | ||
fmt.Sprintf("desired format of the output, allowed formats:%v", convert.AllFormats)) | ||
convertCmd.Flags().StringVar(&convertCmdInputFile, "input-file", "", | ||
"file containing configuration that needs to be converted. Use '-' to read from stdin.") | ||
convertCmd.Flags().StringVar(&convertCmdOutputFile, "output-file", "", | ||
"file to which to write configuration after conversion. Use '-' to write to stdout.") | ||
rootCmd.AddCommand(convertCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package convert | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/kong/deck/file" | ||
"github.com/kong/deck/utils" | ||
"github.com/kong/go-kong/kong" | ||
) | ||
|
||
type Format string | ||
|
||
const ( | ||
FormatKongGateway Format = "kong-gateway" | ||
FormatKonnect Format = "konnect" | ||
) | ||
|
||
var ( | ||
AllFormats = []Format{FormatKongGateway, FormatKonnect} | ||
|
||
conversions = map[Format]map[Format]bool{ | ||
FormatKongGateway: { | ||
FormatKonnect: true, | ||
}, | ||
} | ||
) | ||
|
||
func validConversion(from, to Format) (bool, error) { | ||
if fromMap, ok := conversions[from]; ok { | ||
if _, ok := fromMap[to]; ok { | ||
return ok, nil | ||
} | ||
} | ||
|
||
return false, fmt.Errorf("cannot convert from '%s' to '%s' format", from, to) | ||
} | ||
|
||
func ParseFormat(key string) (Format, error) { | ||
format := Format(strings.ToLower(key)) | ||
switch format { | ||
case FormatKongGateway: | ||
return FormatKongGateway, nil | ||
case FormatKonnect: | ||
return FormatKonnect, nil | ||
default: | ||
return "", fmt.Errorf("invalid format: '%v'", key) | ||
} | ||
} | ||
|
||
func Convert(inputFilename, outputFilename string, from, to Format) error { | ||
if valid, err := validConversion(from, to); !valid { | ||
return err | ||
} | ||
|
||
switch { | ||
case from == FormatKongGateway && to == FormatKonnect: | ||
return convertKongGatewayToKonnect(inputFilename, outputFilename) | ||
default: | ||
return fmt.Errorf("cannot convert from '%s' to '%s' format", from, to) | ||
} | ||
} | ||
|
||
func convertKongGatewayToKonnect(inputFilename, outputFilename string) error { | ||
inputContent, err := file.GetContentFromFiles([]string{inputFilename}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
outputContent := inputContent.DeepCopy() | ||
|
||
for _, service := range outputContent.Services { | ||
servicePackage, err := kongServiceToKonnectServicePackage(service) | ||
if err != nil { | ||
return err | ||
} | ||
outputContent.ServicePackages = append(outputContent.ServicePackages, servicePackage) | ||
} | ||
// Remove Kong Services from the file because all of them have been converted | ||
// into Service packages | ||
outputContent.Services = nil | ||
|
||
// all other entities are left as is | ||
|
||
if err := file.WriteContentToFile(outputContent, outputFilename, file.YAML); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func kongServiceToKonnectServicePackage(service file.FService) (file.FServicePackage, error) { | ||
if service.Name == nil { | ||
return file.FServicePackage{}, fmt.Errorf("kong service with id '%s' doesn't have a name,"+ | ||
"all services must be named to convert them from %s to %s format", | ||
*service.ID, FormatKongGateway, FormatKonnect) | ||
} | ||
|
||
serviceName := *service.Name | ||
// Kong service MUST contain an ID and no name in Konnect representation | ||
serviceCopy := service.DeepCopy() | ||
serviceCopy.Name = nil | ||
serviceCopy.ID = kong.String(utils.UUID()) | ||
|
||
// convert Kong Service to a Service Package | ||
return file.FServicePackage{ | ||
Name: &serviceName, | ||
Description: kong.String("placeholder description for " + serviceName + " service package"), | ||
Versions: []file.FServiceVersion{ | ||
{ | ||
Version: kong.String("v1"), | ||
Implementation: &file.Implementation{ | ||
Type: utils.ImplementationTypeKongGateway, | ||
Kong: &file.Kong{ | ||
Service: serviceCopy, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, nil | ||
} |
Oops, something went wrong.