Skip to content

Commit

Permalink
support launch app via its name though clusterfile or cli (#1917)
Browse files Browse the repository at this point in the history
* support launch app via its name though clusterfile or cli

* fix bug: run app
  • Loading branch information
kakaZhou719 authored Dec 16, 2022
1 parent 92521b9 commit ee33b05
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 112 deletions.
2 changes: 0 additions & 2 deletions build/kubefile/parser/app_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ func (kp *KubefileParser) processApp(node *Node, result *KubefileResult) error {
tmpLine := strings.Join(append([]string{command.Copy}, append(filesToCopy, destDir)...), " ")
result.Dockerfile = mergeLines(result.Dockerfile, tmpLine)
result.legacyContext.apps2Files[appName] = append([]string{}, filesToCopy...)

appType, launchFiles, err := getApplicationType(filesToCopy)
if err != nil {
return fmt.Errorf("error in judging the application type: %v", err)
Expand All @@ -105,7 +104,6 @@ func (kp *KubefileParser) processApp(node *Node, result *KubefileResult) error {
appType,
launchFiles,
).(*v1.Application)

result.Applications[v1App.Name()] = v1App
return nil
}
Expand Down
47 changes: 10 additions & 37 deletions build/kubefile/parser/kubefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,12 @@ import (

"github.com/sirupsen/logrus"

"github.com/sealerio/sealer/pkg/define/application"

"github.com/sealerio/sealer/pkg/define/options"

parse2 "github.com/containers/buildah/pkg/parse"

"github.com/sealerio/sealer/pkg/imageengine"

v1 "github.com/sealerio/sealer/pkg/define/application/v1"

"github.com/sealerio/sealer/pkg/define/application/version"

"github.com/pkg/errors"
Expand All @@ -53,7 +49,8 @@ type LegacyContext struct {

type KubefileResult struct {
Dockerfile string
LaunchList []string
RawCmds []string
AppNames []string
Applications map[string]version.VersionedApplication
legacyContext LegacyContext
}
Expand Down Expand Up @@ -85,7 +82,8 @@ func (kp *KubefileParser) generateResult(mainNode *Node) (*KubefileResult, error
directories: []string{},
apps2Files: map[string][]string{},
},
LaunchList: []string{},
RawCmds: []string{},
AppNames: []string{},
}

err error
Expand Down Expand Up @@ -164,45 +162,20 @@ func (kp *KubefileParser) processOnCmd(result *KubefileResult, node *Node) error
func (kp *KubefileParser) processCmds(node *Node, result *KubefileResult) error {
cmdsNode := node.Next
for iter := cmdsNode; iter != nil; iter = iter.Next {
result.LaunchList = append(result.LaunchList, iter.Value)
result.RawCmds = append(result.RawCmds, iter.Value)
}
return nil
}

func (kp *KubefileParser) processLaunch(node *Node, result *KubefileResult) error {
launchApp := func(appName string) (string, error) {
appName = strings.TrimSpace(appName)
app, ok := result.Applications[appName]
if !ok {
return "", errors.Errorf("application %s does not exist in the image", appName)
}

v1app := app.(*v1.Application)
path := kp.appRootPathFunc(appName)
switch v1app.Type() {
case application.KubeApp:
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())
}
}

appNode := node.Next
for iter := appNode; iter != nil; iter = iter.Next {
app := iter.Value
lstr, err := launchApp(app)
if err != nil {
return err
appName := iter.Value
appName = strings.TrimSpace(appName)
if _, ok := result.Applications[appName]; !ok {
return errors.Errorf("application %s does not exist in the image", appName)
}
result.LaunchList = append(result.LaunchList, lstr)
result.AppNames = append(result.AppNames, appName)
}

return nil
Expand Down
22 changes: 10 additions & 12 deletions build/kubefile/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (

const (
//nginxDemoURL = "https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/deployment.yaml"

)

var testParser *KubefileParser
Expand Down Expand Up @@ -63,7 +62,8 @@ func TestParserKubeApp(t *testing.T) {
text = fmt.Sprintf(`
FROM busybox as base
APP %s local://%s
`, app1Name, nginxDemoPath)
LAUNCH ["%s"]
`, app1Name, nginxDemoPath, app1Name)
)

reader := bytes.NewReader([]byte(text))
Expand All @@ -86,12 +86,12 @@ copy %s %s
result.Dockerfile = strings.TrimSpace(result.Dockerfile)
expectedResult := &KubefileResult{
Dockerfile: strings.TrimSpace(expectedText),
LaunchList: []string{},
AppNames: []string{app1Name},
Applications: map[string]version.VersionedApplication{
app1Name: v1.NewV1Application(
app1Name,
application.KubeApp,
[]string{},
[]string{nginxDemoPath},
),
},
}
Expand All @@ -100,7 +100,7 @@ copy %s %s
assert.Equal(t, len(expectedResult.Applications), len(result.Applications))
assert.Equal(t, expectedResult.Applications[app1Name].Name(), result.Applications[app1Name].Name())
assert.Equal(t, expectedResult.Applications[app1Name].Type(), result.Applications[app1Name].Type())
assert.Equal(t, expectedResult.LaunchList, result.LaunchList)
assert.Equal(t, expectedResult.AppNames, result.AppNames)
}

func TestParserHelmApp(t *testing.T) {
Expand Down Expand Up @@ -149,14 +149,12 @@ copy %s %s
result.Dockerfile = strings.TrimSpace(result.Dockerfile)
expectedResult := &KubefileResult{
Dockerfile: strings.TrimSpace(expectedText),
LaunchList: []string{
fmt.Sprintf("helm install %s %s", app1Name, app1Path),
},
AppNames: []string{app1Name},
Applications: map[string]version.VersionedApplication{
app1Name: v1.NewV1Application(
app1Name,
application.HelmApp,
[]string{},
[]string{githubAppPath},
),
},
}
Expand All @@ -165,7 +163,7 @@ copy %s %s
assert.Equal(t, len(expectedResult.Applications), len(result.Applications))
assert.Equal(t, expectedResult.Applications[app1Name].Name(), result.Applications[app1Name].Name())
assert.Equal(t, expectedResult.Applications[app1Name].Type(), result.Applications[app1Name].Type())
assert.Equal(t, expectedResult.LaunchList, result.LaunchList)
assert.Equal(t, expectedResult.AppNames, result.AppNames)
}

func TestParserCMDS(t *testing.T) {
Expand Down Expand Up @@ -206,7 +204,7 @@ FROM busybox as base
result.Dockerfile = strings.TrimSpace(result.Dockerfile)
expectedResult := &KubefileResult{
Dockerfile: strings.TrimSpace(expectedText),
LaunchList: []string{
RawCmds: []string{
"kubectl apply -f abc.yaml",
"kubectl apply -f bcd.yaml",
},
Expand All @@ -215,7 +213,7 @@ FROM busybox as base

assert.Equal(t, expectedResult.Dockerfile, result.Dockerfile)
assert.Equal(t, len(expectedResult.Applications), len(result.Applications))
assert.Equal(t, expectedResult.LaunchList, result.LaunchList)
assert.Equal(t, expectedResult.RawCmds, result.RawCmds)
}

func setupTempContext() (string, error) {
Expand Down
4 changes: 2 additions & 2 deletions build/kubefile/parser/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func isShell(sources ...string) (bool, []string, error) {
func getApplicationType(sources []string) (string, []string, error) {
isy, yamlErr := isYaml(sources...)
if isy {
return application.KubeApp, nil, nil
return application.KubeApp, sources, nil
}

iss, files, shellErr := isShell(sources...)
Expand All @@ -230,7 +230,7 @@ func getApplicationType(sources []string) (string, []string, error) {

ish, helmErr := isHelm(sources...)
if ish {
return application.HelmApp, nil, nil
return application.HelmApp, sources, nil
}

if yamlErr != nil {
Expand Down
4 changes: 3 additions & 1 deletion cmd/sealer/cmd/cluster/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ func NewApplyCmd() *cobra.Command {

if extension.Type == v12.AppInstaller {
logrus.Infof("start to install application: %s", imageName)
return installApplication(imageName, nil, extension, infraDriver, imageEngine, applyMode)
cmds := infraDriver.GetClusterLaunchCmds()
apps := infraDriver.GetClusterLaunchApps()
return installApplication(imageName, cmds, apps, extension, infraDriver, imageEngine, applyMode)
}

client := utils.GetClusterClient()
Expand Down
78 changes: 38 additions & 40 deletions cmd/sealer/cmd/cluster/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,43 +77,6 @@ func NewRunCmd() *cobra.Command {
clusterFile = runFlags.ClusterFile
applyMode = runFlags.Mode
)
imageEngine, err := imageengine.NewImageEngine(imagecommon.EngineGlobalConfigurations{})
if err != nil {
return err
}

extension, err := imageEngine.GetSealerImageExtension(&imagecommon.GetImageAnnoOptions{ImageNameOrID: args[0]})
if err != nil {
return fmt.Errorf("failed to get cluster image extension: %s", err)
}

if extension.Type == v12.AppInstaller {
logrus.Infof("start to install app image: %s", args[0])
cf, err := clusterfile.NewClusterFile(nil)
if err != nil {
return err
}

cluster := cf.GetCluster()
infraDriver, err := infradriver.NewInfraDriver(&cluster)
if err != nil {
return err
}

if err := imageEngine.Pull(&imagecommon.PullOptions{
Quiet: false,
PullPolicy: "missing",
Image: args[0],
Platform: "local",
}); err != nil {
return err
}
return installApplication(args[0], runFlags.LaunchCmds, extension, infraDriver, imageEngine, applyMode)
}

if len(runFlags.LaunchCmds) > 0 {
return fmt.Errorf("this command parameter (--cmds) is only available to application images")
}

if runFlags.Masters == "" && clusterFile == "" {
return fmt.Errorf("you must input master ip Or use Clusterfile")
Expand Down Expand Up @@ -160,6 +123,30 @@ func NewRunCmd() *cobra.Command {
return err
}

imageEngine, err := imageengine.NewImageEngine(imagecommon.EngineGlobalConfigurations{})
if err != nil {
return err
}

if err = imageEngine.Pull(&imagecommon.PullOptions{
Quiet: false,
PullPolicy: "missing",
Image: cluster.Spec.Image,
Platform: "local",
}); err != nil {
return err
}

extension, err := imageEngine.GetSealerImageExtension(&imagecommon.GetImageAnnoOptions{ImageNameOrID: args[0]})
if err != nil {
return fmt.Errorf("failed to get cluster image extension: %s", err)
}

if extension.Type == v12.AppInstaller {
logrus.Infof("start to install app image: %s", cluster.Spec.Image)
return installApplication(args[0], runFlags.Cmds, runFlags.AppNames, extension, infraDriver, imageEngine, applyMode)
}

return createNewCluster(infraDriver, imageEngine, cf, applyMode)
},
}
Expand All @@ -173,8 +160,8 @@ func NewRunCmd() *cobra.Command {
runCmd.Flags().Uint16Var(&runFlags.Port, "port", 22, "set the sshd service port number for the server (default port: 22)")
runCmd.Flags().StringVar(&runFlags.Pk, "pk", filepath.Join(common.GetHomeDir(), ".ssh", "id_rsa"), "set baremetal server private key")
runCmd.Flags().StringVar(&runFlags.PkPassword, "pk-passwd", "", "set baremetal server private key password")
runCmd.Flags().StringSliceVar(&runFlags.CMDArgs, "cmd-args", []string{}, "set args for image cmd instruction")
runCmd.Flags().StringSliceVar(&runFlags.LaunchCmds, "cmds", []string{}, "override default LaunchCmds of clusterimage")
runCmd.Flags().StringSliceVar(&runFlags.Cmds, "cmds", []string{}, "override default LaunchCmds of clusterimage")
runCmd.Flags().StringSliceVar(&runFlags.AppNames, "apps", []string{}, "override default AppNames of clusterimage")
runCmd.Flags().StringSliceVarP(&runFlags.CustomEnv, "env", "e", []string{}, "set custom environment variables")
runCmd.Flags().StringVarP(&runFlags.ClusterFile, "Clusterfile", "f", "", "Clusterfile path to run a Kubernetes cluster")
runCmd.Flags().StringVar(&runFlags.Mode, "mode", common.ApplyModeApply, "load images to the specified registry in advance")
Expand Down Expand Up @@ -309,8 +296,19 @@ func loadToRegistry(infraDriver infradriver.InfraDriver, distributor imagedistri
return nil
}

func installApplication(appImageName string, launchCmds []string, extension v12.ImageExtension,
func installApplication(appImageName string, cmds []string, appNames []string, extension v12.ImageExtension,
infraDriver infradriver.InfraDriver, imageEngine imageengine.Interface, mode string) error {
if len(cmds) != 0 && len(appNames) != 0 {
return fmt.Errorf("only one can be selected to do overwrite for launchCmds(%s) and appNames(%s)", cmds, appNames)
}

var launchCmds []string
if len(cmds) != 0 {
launchCmds = cmds
} else {
launchCmds = clusterruntime.GetAppLaunchCmdsByNames(appNames, extension.Applications)
}

clusterHosts := infraDriver.GetHostIPList()

clusterHostsPlatform, err := infraDriver.GetHostsPlatform(clusterHosts)
Expand Down
3 changes: 2 additions & 1 deletion cmd/sealer/cmd/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ func buildImageExtensionOnResult(result *parser.KubefileResult, imageType string
for _, app := range result.Applications {
extension.Applications = append(extension.Applications, app)
}
extension.Launch.Cmds = result.LaunchList
extension.Launch.Cmds = result.RawCmds
extension.Launch.AppNames = result.AppNames
return extension
}

Expand Down
10 changes: 6 additions & 4 deletions cmd/sealer/cmd/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ type Flags struct {
CMDArgs []string
Mode string
ClusterFile string
// override default LaunchCmds of clusterimage
LaunchCmds []string
// maybe we can support to override default LaunchArgs of clusterimage to render LaunchCmds.
LaunchArgs []string

// override default Cmds of clusterimage
Cmds []string
// override default APPNames of clusterimage
// Only one can be selected for LaunchCmds and AppNames
AppNames []string
}

type ApplyFlags struct {
Expand Down
Loading

0 comments on commit ee33b05

Please sign in to comment.