Skip to content

Commit

Permalink
refactor: Add validation, formatting and errors for kompose conversion
Browse files Browse the repository at this point in the history
code

Signed-off-by: Nithish <[email protected]>
  • Loading branch information
Nithish authored and Nithish committed Jun 18, 2022
1 parent 7f12876 commit 3f6f61a
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 9 deletions.
2 changes: 1 addition & 1 deletion helpers/component_info.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "meshkit",
"type": "library",
"next_error_code": 11076
"next_error_code": 11080
}
12 changes: 11 additions & 1 deletion utils/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,20 @@ var (
ErrReadingLocalFileCode = "11054"
ErrGettingLatestReleaseTagCode = "11055"
ErrInvalidProtocol = errors.New(ErrInvalidProtocolCode, errors.Alert, []string{"invalid protocol: only http, https and file are valid protocols"}, []string{}, []string{"Network protocol is incorrect"}, []string{"Make sure to specify the right network protocol"})
ErrMissingFieldCode = "11076"
ErrExpectedTypeMismatchCode = "11079"
)

func ErrExpectedTypeMismatch(err error, expectedType string) error {
return errors.New(ErrExpectedTypeMismatchCode, errors.Alert, []string{"Expected the type to be: ", expectedType}, []string{err.Error()}, []string{"Invalid manifest"}, []string{"Make sure that the value provided in the manifest has the needed type."})
}

func ErrMissingField(err error, missingFieldName string) error {
return errors.New(ErrMissingFieldCode, errors.Alert, []string{"Missing field or property with name: ", missingFieldName}, []string{err.Error()}, []string{"Invalid manifest"}, []string{"Make sure that the concerned data type has all the required fields/values."})
}

func ErrUnmarshal(err error) error {
return errors.New(ErrUnmarshalCode, errors.Alert, []string{"Unmarshal unknown error: %s"}, []string{err.Error()}, []string{"Invalid object format"}, []string{"Make sure to input a valid JSON object"})
return errors.New(ErrUnmarshalCode, errors.Alert, []string{"Unmarshal unknown error: "}, []string{err.Error()}, []string{"Invalid object format"}, []string{"Make sure to input a valid JSON object"})
}

func ErrUnmarshalInvalid(err error, typ reflect.Type) error {
Expand Down
5 changes: 3 additions & 2 deletions utils/kubernetes/kompose/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/kubernetes/kompose/pkg/app"
"github.com/kubernetes/kompose/pkg/kobject"
"github.com/layer5io/meshkit/utils"
"gopkg.in/yaml.v2"
)

Expand All @@ -15,8 +16,8 @@ var (
)

// converts a given docker-compose file into kubernetes manifests
func Convert(dockerCompose string) (string, error) {
err := ioutil.WriteFile("temp.data", []byte(dockerCompose), 0666)
func Convert(dockerCompose []byte) (string, error) {
err := utils.CreateFile(dockerCompose, "temp.data", "./")
if err != nil {
return "", ErrCvrtKompose(err)
}
Expand Down
12 changes: 11 additions & 1 deletion utils/kubernetes/kompose/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@ package kompose
import "github.com/layer5io/meshkit/errors"

const (
ErrCvrtKomposeCode = "11075"
ErrCvrtKomposeCode = "11075"
ErrNoVersionCode = "11077"
ErrIncompatibleVersionCode = "11078"
)

func ErrCvrtKompose(err error) error {
return errors.New(ErrCvrtKomposeCode, errors.Alert, []string{"Error converting the docker compose file into kubernetes manifests"}, []string{err.Error()}, []string{"Could not convert docker-compose file into kubernetes manifests"}, []string{"Make sure the docker-compose file is valid", ""})
}

func ErrNoVersion() error {
return errors.New(ErrNoVersionCode, errors.Alert, []string{"version not found in the docker compose file"}, []string{"The docker compose file does not have version field in it. The underlying tool that is used for conversion mandates the presence of version field."}, []string{"Since the Docker Compose specification does not mandate the version field from version 3 onwards, most sources do not provide them."}, []string{"Make sure that the compose file has version specified,", "Add any version less than or equal to 3.3 if you cannot get the exact version from the source"})
}

func ErrIncompatibleVersion() error {
return errors.New(ErrIncompatibleVersionCode, errors.Alert, []string{"This version of docker compose file is not compatible."}, []string{"This docker compose file is invalid since it's version is incompatible."}, []string{"docker compose file with version greater than 3.3 is probably being used"}, []string{"Make sure that the compose file has version less than or equal to 3.3,", ""})
}
4 changes: 1 addition & 3 deletions utils/kubernetes/kompose/models/composefile.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package models

import "encoding/json"

type DockerComposeFile struct {
Version json.Number `yaml:"version" json:"version"`
Version string `yaml:"version" json:"version"`
Services interface{} `yaml:"services" json:"services"` // more constraints should be added to this type
}
48 changes: 47 additions & 1 deletion utils/kubernetes/kompose/utils.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package kompose

import (
"fmt"
"strconv"

errors "github.com/layer5io/meshkit/utils"
"github.com/layer5io/meshkit/utils/kubernetes/kompose/models"
"gopkg.in/yaml.v2"
)
Expand All @@ -11,8 +15,50 @@ func IsManifestADockerCompose(yamlManifest []byte) bool {
if err := yaml.Unmarshal(yamlManifest, &data); err != nil {
return false
}
if data.Version == "" {
if data.Services == nil {
return false
}
return true
}

// VaildateDockerComposeFile takes in a manifest and returns validates it
func VaildateDockerComposeFile(yamlManifest []byte) error {
data := models.DockerComposeFile{}
if err := yaml.Unmarshal(yamlManifest, &data); err != nil {
return errors.ErrUnmarshal(err)
}
if data.Version == "" {
return errors.ErrMissingField(ErrNoVersion(), "Version")
}
versionFloatVal, err := strconv.ParseFloat(data.Version, 64)
if err != nil {
return errors.ErrExpectedTypeMismatch(err, "float")
} else {
if versionFloatVal > 3.3 {
// kompose throws a fatal error when version exceeds 3.3
// need this till this PR gets merged https://github.com/kubernetes/kompose/pull/1440(move away from libcompose to compose-go)
return ErrIncompatibleVersion()
}
}
if data.Services == nil {
return errors.ErrMissingField(fmt.Errorf("Services field is missing in the docker compose file"), "Services")
}
return nil
}

// FormatComposeFile takes in a pointer to the compose file byte array and formats it so that it is compatible with `Kompose`
// it expects a validated docker compose file and does not validate
func FormatComposeFile(yamlManifest *[]byte) error {
data := models.DockerComposeFile{}
err := yaml.Unmarshal(*yamlManifest, &data)
if err != nil {
return errors.ErrUnmarshal(err)
}
data.Version = fmt.Sprintf("%s", data.Version)
out, err := yaml.Marshal(data)
if err != nil {
return errors.ErrMarshal(err)
}
*yamlManifest = out
return nil
}

0 comments on commit 3f6f61a

Please sign in to comment.