Skip to content

Commit

Permalink
feat: add more apis for 'kpm run' to get the full compile results
Browse files Browse the repository at this point in the history
  • Loading branch information
zong-zhe committed Sep 5, 2023
1 parent d8f53cf commit ffaefad
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 79 deletions.
188 changes: 110 additions & 78 deletions pkg/api/kpm_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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'.
Expand All @@ -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)
}
39 changes: 39 additions & 0 deletions pkg/api/kpm_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
1 change: 1 addition & 0 deletions pkg/api/test_data/test_run_pkg_in_path/expected.json
Original file line number Diff line number Diff line change
@@ -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}]}]}}}}}]
1 change: 1 addition & 0 deletions pkg/api/test_data/test_run_tar_in_path/expected.json
Original file line number Diff line number Diff line change
@@ -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}]}]}}}}}]
2 changes: 1 addition & 1 deletion pkg/package/test_data/test_data_add_deps/kcl.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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"

0 comments on commit ffaefad

Please sign in to comment.