From ffaefadd072bed7128b2671738734f0d1d5f0c6d Mon Sep 17 00:00:00 2001 From: zongz Date: Tue, 5 Sep 2023 17:26:42 +0800 Subject: [PATCH] feat: add more apis for 'kpm run' to get the full compile results --- pkg/api/kpm_run.go | 188 ++++++++++-------- pkg/api/kpm_run_test.go | 39 ++++ .../test_run_pkg_in_path/expected.json | 1 + .../test_run_tar_in_path/expected.json | 1 + .../test_data/test_data_add_deps/kcl.mod | 2 +- 5 files changed, 152 insertions(+), 79 deletions(-) create mode 100644 pkg/api/test_data/test_run_pkg_in_path/expected.json create mode 100644 pkg/api/test_data/test_run_tar_in_path/expected.json diff --git a/pkg/api/kpm_run.go b/pkg/api/kpm_run.go index 7f607ab2..f374b154 100644 --- a/pkg/api/kpm_run.go +++ b/pkg/api/kpm_run.go @@ -18,113 +18,111 @@ import ( // RunTar will compile the kcl package from a kcl package tar. func RunTar(tarPath string, opts *opt.CompileOptions) (string, error) { - absTarPath, err := absTarPath(tarPath) - if err != nil { - return "", err - } - // Extract the tar package to a directory with the same name. - // e.g. - // 'xxx/xxx/xxx/test.tar' will be extracted to the directory 'xxx/xxx/xxx/test'. - destDir := strings.TrimSuffix(absTarPath, filepath.Ext(absTarPath)) - err = utils.UnTarDir(absTarPath, destDir) - if err != nil { - return "", err - } - - opts.SetPkgPath(destDir) // The directory after extracting the tar package is taken as the root directory of the package, // and kclvm is called to compile the kcl program under the 'destDir'. // e.g. // if the tar path is 'xxx/xxx/xxx/test.tar', // the 'xxx/xxx/xxx/test' will be taken as the root path of the kcl package to compile. - compileResult, compileErr := RunPkgInPath(opts) + compileResult, compileErr := RunTarPkg(tarPath, opts) if compileErr != nil { return "", compileErr } - return compileResult, nil + return compileResult.GetRawYamlResult(), nil } const KCL_PKG_TAR = "*.tar" // RunOci will compile the kcl package from an OCI reference. func RunOci(ociRef, version string, opts *opt.CompileOptions) (string, error) { - ociOpts, err := opt.ParseOciOptionFromString(ociRef, version) + compileResult, compileErr := RunOciPkg(ociRef, version, opts) + if compileErr != nil { + return "", compileErr + } + return compileResult.GetRawYamlResult(), nil +} + +// RunPkg will compile current kcl package. +func RunPkg(opts *opt.CompileOptions) (string, error) { + + compileResult, err := RunCurrentPkg(opts) if err != nil { return "", err } - // 1. Create the temporary directory to pull the tar. - tmpDir, err := os.MkdirTemp("", "") + return compileResult.GetRawYamlResult(), nil +} + +// RunPkgInPath will load the 'KclPkg' from path 'pkgPath'. +// And run the kcl package with entry file in 'entryFilePath' in 'vendorMode'. +func RunPkgInPath(opts *opt.CompileOptions) (string, error) { + // Call the kcl compiler. + compileResult, err := RunPkgWithOpt(opts) if err != nil { - return "", errors.InternalBug + return "", err } - // clean the temp dir. - defer os.RemoveAll(tmpDir) - localPath := ociOpts.AddStoragePathSuffix(tmpDir) - - // 2. Pull the tar. - err = oci.Pull(localPath, ociOpts.Reg, ociOpts.Repo, ociOpts.Tag) + return compileResult.GetRawYamlResult(), nil +} - if err != (*reporter.KpmEvent)(nil) { - return "", err +// absTarPath checks whether path 'tarPath' exists and whether path 'tarPath' ends with '.tar' +// And after checking, absTarPath return the abs path for 'tarPath'. +func absTarPath(tarPath string) (string, error) { + absTarPath, err := filepath.Abs(tarPath) + if err != nil { + return "", errors.InternalBug } - // 3.Get the (*.tar) file path. - matches, err := filepath.Glob(filepath.Join(localPath, KCL_PKG_TAR)) - if err != nil || len(matches) != 1 { - return "", errors.FailedPull + if filepath.Ext(absTarPath) != ".tar" { + return "", errors.InvalidKclPacakgeTar + } else if !utils.DirExists(absTarPath) { + return "", errors.KclPacakgeTarNotFound } - return RunTar(matches[0], opts) + return absTarPath, nil } -// RunPkg will compile current kcl package. -func RunPkg(opts *opt.CompileOptions) (string, error) { - - // If no tar packages specified by "--tar" to run - // kpm will take the current directory ($PWD) as the root of the kcl package and compile. - pwd, err := os.Getwd() - opts.SetPkgPath(pwd) - +// getAbsInputPath will return the abs path of the file path described by '--input'. +// If the path exists after 'inputPath' is computed as a full path, it will be returned. +// If not, the kpm checks whether the full path of 'pkgPath/inputPath' exists, +// If the full path of 'pkgPath/inputPath' exists, it will be returned. +// If not, getAbsInputPath returns 'entry file not found' error. +func getAbsInputPath(pkgPath string, inputPath string) (string, error) { + absPath, err := filepath.Abs(filepath.Join(pkgPath, inputPath)) if err != nil { - reporter.ExitWithReport("kpm: internal bug: failed to load working directory") + return "", err } - compileResult, err := RunPkgInPath(opts) - if err != nil { - return "", err + if utils.DirExists(absPath) { + return absPath, nil } - return compileResult, nil + return "", errors.EntryFileNotFound } -// RunPkgInPath will load the 'KclPkg' from path 'pkgPath'. -// And run the kcl package with entry file in 'entryFilePath' in 'vendorMode'. -func RunPkgInPath(opts *opt.CompileOptions) (string, error) { - +// RunPkgWithOpt will compile the kcl package with the compile options. +func RunPkgWithOpt(opts *opt.CompileOptions) (*kcl.KCLResultList, error) { pkgPath, err := filepath.Abs(opts.PkgPath()) if err != nil { - return "", errors.InternalBug + return nil, errors.InternalBug } kclPkg, err := pkg.LoadKclPkg(pkgPath) if err != nil { - return "", errors.FailedToLoadPackage + return nil, errors.FailedToLoadPackage } kclPkg.SetVendorMode(opts.IsVendor()) globalPkgPath, err := env.GetAbsPkgPath() if err != nil { - return "", err + return nil, err } err = kclPkg.ValidateKpmHome(globalPkgPath) if err != (*reporter.KpmEvent)(nil) { - return "", err + return nil, err } if len(opts.Entries()) > 0 { @@ -143,7 +141,6 @@ func RunPkgInPath(opts *opt.CompileOptions) (string, error) { // no entry opts.Merge(kcl.WithKFilenames(opts.PkgPath())) } - // set the 'kcl.mod' path as the work dir. opts.Merge(kcl.WithWorkDir(opts.PkgPath())) // Calculate the absolute path of entry file described by '--input'. @@ -156,43 +153,78 @@ func RunPkgInPath(opts *opt.CompileOptions) (string, error) { ) if err != nil { - return "", reporter.NewErrorEvent(reporter.CompileFailed, err, "failed to compile the kcl package") + return nil, reporter.NewErrorEvent(reporter.CompileFailed, err, "failed to compile the kcl package") } - return compileResult.GetRawYamlResult(), nil + return compileResult, nil } -// absTarPath checks whether path 'tarPath' exists and whether path 'tarPath' ends with '.tar' -// And after checking, absTarPath return the abs path for 'tarPath'. -func absTarPath(tarPath string) (string, error) { - absTarPath, err := filepath.Abs(tarPath) +// RunCurrentPkg will compile the current kcl package. +func RunCurrentPkg(opts *opt.CompileOptions) (*kcl.KCLResultList, error) { + pwd, err := os.Getwd() + opts.SetPkgPath(pwd) + if err != nil { - return "", errors.InternalBug + reporter.ExitWithReport("kpm: internal bug: failed to load working directory") } - if filepath.Ext(absTarPath) != ".tar" { - return "", errors.InvalidKclPacakgeTar - } else if !utils.DirExists(absTarPath) { - return "", errors.KclPacakgeTarNotFound + return RunPkgWithOpt(opts) +} + +// RunTarPkg will compile the kcl package from a kcl package tar. +func RunTarPkg(tarPath string, opts *opt.CompileOptions) (*kcl.KCLResultList, error) { + absTarPath, err := absTarPath(tarPath) + if err != nil { + return nil, err + } + // Extract the tar package to a directory with the same name. + // e.g. + // 'xxx/xxx/xxx/test.tar' will be extracted to the directory 'xxx/xxx/xxx/test'. + destDir := strings.TrimSuffix(absTarPath, filepath.Ext(absTarPath)) + err = utils.UnTarDir(absTarPath, destDir) + if err != nil { + return nil, err } - return absTarPath, nil + opts.SetPkgPath(destDir) + // The directory after extracting the tar package is taken as the root directory of the package, + // and kclvm is called to compile the kcl program under the 'destDir'. + // e.g. + // if the tar path is 'xxx/xxx/xxx/test.tar', + // the 'xxx/xxx/xxx/test' will be taken as the root path of the kcl package to compile. + return RunPkgWithOpt(opts) } -// getAbsInputPath will return the abs path of the file path described by '--input'. -// If the path exists after 'inputPath' is computed as a full path, it will be returned. -// If not, the kpm checks whether the full path of 'pkgPath/inputPath' exists, -// If the full path of 'pkgPath/inputPath' exists, it will be returned. -// If not, getAbsInputPath returns 'entry file not found' error. -func getAbsInputPath(pkgPath string, inputPath string) (string, error) { - absPath, err := filepath.Abs(filepath.Join(pkgPath, inputPath)) +// RunOciPkg will compile the kcl package from an OCI reference. +func RunOciPkg(ociRef, version string, opts *opt.CompileOptions) (*kcl.KCLResultList, error) { + ociOpts, err := opt.ParseOciOptionFromString(ociRef, version) + if err != nil { - return "", err + return nil, err } - if utils.DirExists(absPath) { - return absPath, nil + // 1. Create the temporary directory to pull the tar. + tmpDir, err := os.MkdirTemp("", "") + if err != nil { + return nil, errors.InternalBug } + // clean the temp dir. + defer os.RemoveAll(tmpDir) - return "", errors.EntryFileNotFound + localPath := ociOpts.AddStoragePathSuffix(tmpDir) + + // 2. Pull the tar. + err = oci.Pull(localPath, ociOpts.Reg, ociOpts.Repo, ociOpts.Tag) + + if err != (*reporter.KpmEvent)(nil) { + return nil, err + } + + // 3.Get the (*.tar) file path. + matches, err := filepath.Glob(filepath.Join(localPath, KCL_PKG_TAR)) + if err != nil || len(matches) != 1 { + return nil, errors.FailedPull + } + + return RunTarPkg(matches[0], opts) } diff --git a/pkg/api/kpm_run_test.go b/pkg/api/kpm_run_test.go index 76568ae4..a314dbbb 100644 --- a/pkg/api/kpm_run_test.go +++ b/pkg/api/kpm_run_test.go @@ -122,3 +122,42 @@ func TestRunWithWorkdir(t *testing.T) { assert.Equal(t, err, nil) assert.Equal(t, result, "base: base\nmain: main") } + +func TestRunWithOpts(t *testing.T) { + pkgPath := getTestDir("test_run_pkg_in_path") + opts := opt.DefaultCompileOptions() + opts.AddEntry(filepath.Join(pkgPath, "test_kcl", "main.k")) + opts.SetPkgPath(filepath.Join(pkgPath, "test_kcl")) + result, err := RunPkgWithOpt(opts) + assert.Equal(t, err, nil) + expected, _ := os.ReadFile(filepath.Join(pkgPath, "expected")) + assert.Equal(t, utils.RmNewline(string(result.GetRawYamlResult())), utils.RmNewline(string(expected))) + expectedJson, _ := os.ReadFile(filepath.Join(pkgPath, "expected.json")) + assert.Equal(t, utils.RmNewline(string(result.GetRawJsonResult())), utils.RmNewline(string(expectedJson))) +} + +func TestRunTarPkg(t *testing.T) { + pkgPath := getTestDir("test_run_tar_in_path") + tarPath, _ := filepath.Abs(filepath.Join(pkgPath, "test.tar")) + untarPath := filepath.Join(pkgPath, "test") + expectPath := filepath.Join(pkgPath, "expected") + expectPathJson := filepath.Join(pkgPath, "expected.json") + + if utils.DirExists(untarPath) { + os.RemoveAll(untarPath) + } + + expectedResult, _ := os.ReadFile(expectPath) + expectedResultJson, _ := os.ReadFile(expectPathJson) + opts := opt.DefaultCompileOptions() + opts.SetVendor(true) + gotResult, err := RunTarPkg(tarPath, opts) + assert.Equal(t, err, nil) + assert.Equal(t, utils.RmNewline(string(expectedResult)), utils.RmNewline(gotResult.GetRawYamlResult())) + assert.Equal(t, utils.RmNewline(string(expectedResultJson)), utils.RmNewline(gotResult.GetRawJsonResult())) + assert.Equal(t, utils.DirExists(untarPath), true) + + if utils.DirExists(untarPath) { + os.RemoveAll(untarPath) + } +} diff --git a/pkg/api/test_data/test_run_pkg_in_path/expected.json b/pkg/api/test_data/test_run_pkg_in_path/expected.json new file mode 100644 index 00000000..69611a84 --- /dev/null +++ b/pkg/api/test_data/test_run_pkg_in_path/expected.json @@ -0,0 +1 @@ +[{"demo": {"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "nginx-deployment"}, "spec": {"replicas": 3, "selector": {"matchLabels": {"app": "nginx"}}, "template": {"metadata": {"labels": {"app": "nginx"}}, "spec": {"containers": [{"image": "nginx:1.14.2", "name": "nginx", "ports": [{"containerPort": 80}]}]}}}}}] \ No newline at end of file diff --git a/pkg/api/test_data/test_run_tar_in_path/expected.json b/pkg/api/test_data/test_run_tar_in_path/expected.json new file mode 100644 index 00000000..69611a84 --- /dev/null +++ b/pkg/api/test_data/test_run_tar_in_path/expected.json @@ -0,0 +1 @@ +[{"demo": {"apiVersion": "apps/v1", "kind": "Deployment", "metadata": {"name": "nginx-deployment"}, "spec": {"replicas": 3, "selector": {"matchLabels": {"app": "nginx"}}, "template": {"metadata": {"labels": {"app": "nginx"}}, "spec": {"containers": [{"image": "nginx:1.14.2", "name": "nginx", "ports": [{"containerPort": 80}]}]}}}}}] \ No newline at end of file diff --git a/pkg/package/test_data/test_data_add_deps/kcl.mod b/pkg/package/test_data/test_data_add_deps/kcl.mod index 72026f01..23d46102 100644 --- a/pkg/package/test_data/test_data_add_deps/kcl.mod +++ b/pkg/package/test_data/test_data_add_deps/kcl.mod @@ -4,5 +4,5 @@ edition = "0.0.1" version = "0.0.1" [dependencies] -oci_name = "test_tag" name = { git = "test_url", tag = "test_tag" } +oci_name = "test_tag"