Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more apis for 'kpm run' to get the full compile results #177

Merged
merged 1 commit into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
Loading