From 7ff33587ff12af5d058c4cd597762d5846fc2ebb Mon Sep 17 00:00:00 2001 From: kakzhou719 Date: Tue, 22 Nov 2022 15:34:20 +0800 Subject: [PATCH] feat: add shell type for APP instruction --- build/kubefile/parser/app_handler.go | 19 +--- build/kubefile/parser/image_engine_test.go | 2 + build/kubefile/parser/kubefile.go | 6 + build/kubefile/parser/parse_test.go | 2 + build/kubefile/parser/utils.go | 126 +++++++++++++++++++++ pkg/define/application/types.go | 5 +- pkg/define/application/v1/application.go | 20 ++-- pkg/define/application/version/version.go | 2 + 8 files changed, 157 insertions(+), 25 deletions(-) diff --git a/build/kubefile/parser/app_handler.go b/build/kubefile/parser/app_handler.go index 7997fb3ba74..964ac62760b 100644 --- a/build/kubefile/parser/app_handler.go +++ b/build/kubefile/parser/app_handler.go @@ -20,12 +20,8 @@ import ( "path/filepath" "strings" - "github.com/sealerio/sealer/pkg/define/application" - - "github.com/sealerio/sealer/build/kubefile/command" - "github.com/pkg/errors" - + "github.com/sealerio/sealer/build/kubefile/command" v1 "github.com/sealerio/sealer/pkg/define/application/v1" ) @@ -99,24 +95,15 @@ func (kp *KubefileParser) processApp(node *Node, result *KubefileResult) error { result.Dockerfile = mergeLines(result.Dockerfile, tmpLine) result.legacyContext.apps2Files[appName] = append([]string{}, filesToCopy...) - isH, err := isHelm(filesToCopy...) + appType, launchFiles, err := getApplicationType(filesToCopy) if err != nil { return fmt.Errorf("error in judging the application type: %v", err) } - appType := "" - switch isH { - case true: - appType = application.HelmApp - case false: - appType = application.KubeApp - default: - return errors.Errorf("error in identifying the type of app:%s", appName) - } - v1App := v1.NewV1Application( appName, appType, + launchFiles, ).(*v1.Application) result.Applications[v1App.Name()] = v1App diff --git a/build/kubefile/parser/image_engine_test.go b/build/kubefile/parser/image_engine_test.go index 931bdc6433c..e2c48bd6da1 100644 --- a/build/kubefile/parser/image_engine_test.go +++ b/build/kubefile/parser/image_engine_test.go @@ -30,10 +30,12 @@ var testExtensionWithApp = v1.ImageExtension{ v12.NewV1Application( "es", "helm", + []string{}, ), v12.NewV1Application( "ts", "kube", + []string{}, ), }, } diff --git a/build/kubefile/parser/kubefile.go b/build/kubefile/parser/kubefile.go index 10a9057e8f4..9cc17d0d517 100644 --- a/build/kubefile/parser/kubefile.go +++ b/build/kubefile/parser/kubefile.go @@ -184,6 +184,12 @@ func (kp *KubefileParser) processLaunch(node *Node, result *KubefileResult) erro return fmt.Sprintf("kubectl apply -f %s", path), nil case application.HelmApp: return fmt.Sprintf("helm install %s %s", v1app.Name(), path), nil + case application.ShellApp: + var cmds []string + for _, file := range v1app.LaunchFiles() { + cmds = append(cmds, fmt.Sprintf("bash %s", filepath.Join(path, file))) + } + return strings.Join(cmds, " && "), nil default: return "", errors.Errorf("unexpected application type %s", v1app.Type()) } diff --git a/build/kubefile/parser/parse_test.go b/build/kubefile/parser/parse_test.go index 332bff6565b..8e0a80d040b 100644 --- a/build/kubefile/parser/parse_test.go +++ b/build/kubefile/parser/parse_test.go @@ -91,6 +91,7 @@ copy %s %s app1Name: v1.NewV1Application( app1Name, application.KubeApp, + []string{}, ), }, } @@ -154,6 +155,7 @@ copy %s %s app1Name: v1.NewV1Application( app1Name, application.HelmApp, + []string{}, ), }, } diff --git a/build/kubefile/parser/utils.go b/build/kubefile/parser/utils.go index da88b30a13d..3481d315c32 100644 --- a/build/kubefile/parser/utils.go +++ b/build/kubefile/parser/utils.go @@ -21,6 +21,7 @@ import ( "path/filepath" "strings" + "github.com/sealerio/sealer/pkg/define/application" osi "github.com/sealerio/sealer/utils/os" ) @@ -119,3 +120,128 @@ func isHelm(sources ...string) (bool, error) { return chartInTargetsRoot == 7, nil } + +// isYaml sources slice only has one element +func isYaml(sources ...string) (bool, error) { + isYamlType := func(fileName string) bool { + ext := strings.ToLower(filepath.Ext(fileName)) + if ext == ".yaml" || ext == ".yml" { + return true + } + return false + } + + for _, source := range sources { + s, err := os.Stat(source) + if err != nil { + return false, fmt.Errorf("failed to stat %s: %v", source, err) + } + + if s.IsDir() { + isAllYamlFiles := true + err = filepath.Walk(source, func(path string, f fs.FileInfo, err error) error { + if err != nil { + return err + } + if f.IsDir() { + return nil + } + // make sure all files under source dir is yaml type. + if !isYamlType(f.Name()) { + isAllYamlFiles = false + return filepath.SkipDir + } + return nil + }) + if err != nil { + return false, fmt.Errorf("failed to walk yaml dir %s: %v", source, err) + } + + if isAllYamlFiles { + return true, nil + } + return false, nil + } + if isYamlType(source) { + return true, nil + } + } + + return false, nil +} + +// isShell sources slice only has one element +func isShell(sources ...string) (bool, []string, error) { + var launchFiles []string + isShellType := func(fileName string) bool { + ext := strings.ToLower(filepath.Ext(fileName)) + return ext == ".sh" + } + + for _, source := range sources { + s, err := os.Stat(source) + if err != nil { + return false, nil, fmt.Errorf("failed to stat %s: %v", source, err) + } + if s.IsDir() { + err = filepath.Walk(source, func(path string, f fs.FileInfo, err error) error { + if err != nil { + return err + } + if f.IsDir() { + return nil + } + // todo optimize: use more accurate methods to determine file types. + if !isShellType(f.Name()) { + return filepath.SkipDir + } + + launchFiles = append(launchFiles, path) + return nil + }) + + if err != nil { + return false, nil, fmt.Errorf("failed to walk shell dir %s: %v", source, err) + } + + if len(launchFiles) > 0 { + return true, launchFiles, nil + } + return false, nil, nil + } + if isShellType(source) { + return true, []string{source}, nil + } + } + + return false, nil, nil +} + +func getApplicationType(sources []string) (string, []string, error) { + isy, yamlErr := isYaml(sources...) + if isy { + return application.KubeApp, nil, nil + } + + iss, files, shellErr := isShell(sources...) + if iss { + return application.ShellApp, files, nil + } + + ish, helmErr := isHelm(sources...) + if ish { + return application.HelmApp, nil, nil + } + + if yamlErr != nil { + return "", nil, yamlErr + } + if shellErr != nil { + return "", nil, shellErr + } + if helmErr != nil { + return "", nil, helmErr + } + + return "", nil, fmt.Errorf("unsupported application type in %s,%s,%s", application.KubeApp, application.HelmApp, application.ShellApp) +} diff --git a/pkg/define/application/types.go b/pkg/define/application/types.go index 72f8a583334..4045562ec88 100644 --- a/pkg/define/application/types.go +++ b/pkg/define/application/types.go @@ -15,6 +15,7 @@ package application const ( - KubeApp string = "kube" - HelmApp string = "helm" + KubeApp string = "kube" + HelmApp string = "helm" + ShellApp string = "shell" ) diff --git a/pkg/define/application/v1/application.go b/pkg/define/application/v1/application.go index 64295560fc3..d2235b810ab 100644 --- a/pkg/define/application/v1/application.go +++ b/pkg/define/application/v1/application.go @@ -19,9 +19,10 @@ import ( ) type Application struct { - NameVar string `json:"name"` - TypeVar string `json:"type,omitempty"` - VersionVar string `json:"version,omitempty"` + NameVar string `json:"name"` + TypeVar string `json:"type,omitempty"` + LaunchFilesVar []string `json:"launchfiles,omitempty"` + VersionVar string `json:"version,omitempty"` } func (app *Application) Version() string { @@ -36,12 +37,17 @@ func (app *Application) Type() string { return app.TypeVar } +func (app *Application) LaunchFiles() []string { + return app.LaunchFilesVar +} + func NewV1Application( name string, - appType string) version.VersionedApplication { + appType string, launchFiles []string) version.VersionedApplication { return &Application{ - NameVar: name, - TypeVar: appType, - VersionVar: "v1", + NameVar: name, + TypeVar: appType, + LaunchFilesVar: launchFiles, + VersionVar: "v1", } } diff --git a/pkg/define/application/version/version.go b/pkg/define/application/version/version.go index 627e61e99b0..a8d36875015 100644 --- a/pkg/define/application/version/version.go +++ b/pkg/define/application/version/version.go @@ -21,4 +21,6 @@ type VersionedApplication interface { Name() string Type() string + + LaunchFiles() []string }